From 6738d21137937f4eb2e23bb6d2a3c0496acc04ec Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Thu, 15 Aug 2024 21:39:08 -0400 Subject: [PATCH 01/31] WIP --- api/poktroll/tokenomics/event.pulsar.go | 800 +++++++++++++++++++-- proto/poktroll/tokenomics/event.proto | 11 +- x/tokenomics/keeper/token_logic_modules.go | 159 +++- x/tokenomics/types/errors.go | 53 +- x/tokenomics/types/event.pb.go | 428 +++++++++-- x/tokenomics/types/tx.pb.go | 1 - 6 files changed, 1300 insertions(+), 152 deletions(-) diff --git a/api/poktroll/tokenomics/event.pulsar.go b/api/poktroll/tokenomics/event.pulsar.go index 300c5cb18..ae7a1d67b 100644 --- a/api/poktroll/tokenomics/event.pulsar.go +++ b/api/poktroll/tokenomics/event.pulsar.go @@ -2395,6 +2395,633 @@ func (x *fastReflection_EventApplicationOverserviced) ProtoMethods() *protoiface } } +var ( + md_EventApplicationReimbursementRequest protoreflect.MessageDescriptor + fd_EventApplicationReimbursementRequest_application_addr protoreflect.FieldDescriptor + fd_EventApplicationReimbursementRequest_service_id protoreflect.FieldDescriptor + fd_EventApplicationReimbursementRequest_session_id protoreflect.FieldDescriptor + fd_EventApplicationReimbursementRequest_amount protoreflect.FieldDescriptor +) + +func init() { + file_poktroll_tokenomics_event_proto_init() + md_EventApplicationReimbursementRequest = File_poktroll_tokenomics_event_proto.Messages().ByName("EventApplicationReimbursementRequest") + fd_EventApplicationReimbursementRequest_application_addr = md_EventApplicationReimbursementRequest.Fields().ByName("application_addr") + fd_EventApplicationReimbursementRequest_service_id = md_EventApplicationReimbursementRequest.Fields().ByName("service_id") + fd_EventApplicationReimbursementRequest_session_id = md_EventApplicationReimbursementRequest.Fields().ByName("session_id") + fd_EventApplicationReimbursementRequest_amount = md_EventApplicationReimbursementRequest.Fields().ByName("amount") +} + +var _ protoreflect.Message = (*fastReflection_EventApplicationReimbursementRequest)(nil) + +type fastReflection_EventApplicationReimbursementRequest EventApplicationReimbursementRequest + +func (x *EventApplicationReimbursementRequest) ProtoReflect() protoreflect.Message { + return (*fastReflection_EventApplicationReimbursementRequest)(x) +} + +func (x *EventApplicationReimbursementRequest) slowProtoReflect() protoreflect.Message { + mi := &file_poktroll_tokenomics_event_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_EventApplicationReimbursementRequest_messageType fastReflection_EventApplicationReimbursementRequest_messageType +var _ protoreflect.MessageType = fastReflection_EventApplicationReimbursementRequest_messageType{} + +type fastReflection_EventApplicationReimbursementRequest_messageType struct{} + +func (x fastReflection_EventApplicationReimbursementRequest_messageType) Zero() protoreflect.Message { + return (*fastReflection_EventApplicationReimbursementRequest)(nil) +} +func (x fastReflection_EventApplicationReimbursementRequest_messageType) New() protoreflect.Message { + return new(fastReflection_EventApplicationReimbursementRequest) +} +func (x fastReflection_EventApplicationReimbursementRequest_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_EventApplicationReimbursementRequest +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_EventApplicationReimbursementRequest) Descriptor() protoreflect.MessageDescriptor { + return md_EventApplicationReimbursementRequest +} + +// 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_EventApplicationReimbursementRequest) Type() protoreflect.MessageType { + return _fastReflection_EventApplicationReimbursementRequest_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_EventApplicationReimbursementRequest) New() protoreflect.Message { + return new(fastReflection_EventApplicationReimbursementRequest) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_EventApplicationReimbursementRequest) Interface() protoreflect.ProtoMessage { + return (*EventApplicationReimbursementRequest)(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_EventApplicationReimbursementRequest) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if x.ApplicationAddr != "" { + value := protoreflect.ValueOfString(x.ApplicationAddr) + if !f(fd_EventApplicationReimbursementRequest_application_addr, value) { + return + } + } + if x.ServiceId != "" { + value := protoreflect.ValueOfString(x.ServiceId) + if !f(fd_EventApplicationReimbursementRequest_service_id, value) { + return + } + } + if x.SessionId != "" { + value := protoreflect.ValueOfString(x.SessionId) + if !f(fd_EventApplicationReimbursementRequest_session_id, value) { + return + } + } + if x.Amount != nil { + value := protoreflect.ValueOfMessage(x.Amount.ProtoReflect()) + if !f(fd_EventApplicationReimbursementRequest_amount, 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_EventApplicationReimbursementRequest) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + case "poktroll.tokenomics.EventApplicationReimbursementRequest.application_addr": + return x.ApplicationAddr != "" + case "poktroll.tokenomics.EventApplicationReimbursementRequest.service_id": + return x.ServiceId != "" + case "poktroll.tokenomics.EventApplicationReimbursementRequest.session_id": + return x.SessionId != "" + case "poktroll.tokenomics.EventApplicationReimbursementRequest.amount": + return x.Amount != nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.tokenomics.EventApplicationReimbursementRequest")) + } + panic(fmt.Errorf("message poktroll.tokenomics.EventApplicationReimbursementRequest 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_EventApplicationReimbursementRequest) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + case "poktroll.tokenomics.EventApplicationReimbursementRequest.application_addr": + x.ApplicationAddr = "" + case "poktroll.tokenomics.EventApplicationReimbursementRequest.service_id": + x.ServiceId = "" + case "poktroll.tokenomics.EventApplicationReimbursementRequest.session_id": + x.SessionId = "" + case "poktroll.tokenomics.EventApplicationReimbursementRequest.amount": + x.Amount = nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.tokenomics.EventApplicationReimbursementRequest")) + } + panic(fmt.Errorf("message poktroll.tokenomics.EventApplicationReimbursementRequest 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_EventApplicationReimbursementRequest) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + case "poktroll.tokenomics.EventApplicationReimbursementRequest.application_addr": + value := x.ApplicationAddr + return protoreflect.ValueOfString(value) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.service_id": + value := x.ServiceId + return protoreflect.ValueOfString(value) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.session_id": + value := x.SessionId + return protoreflect.ValueOfString(value) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.amount": + value := x.Amount + return protoreflect.ValueOfMessage(value.ProtoReflect()) + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.tokenomics.EventApplicationReimbursementRequest")) + } + panic(fmt.Errorf("message poktroll.tokenomics.EventApplicationReimbursementRequest 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_EventApplicationReimbursementRequest) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + case "poktroll.tokenomics.EventApplicationReimbursementRequest.application_addr": + x.ApplicationAddr = value.Interface().(string) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.service_id": + x.ServiceId = value.Interface().(string) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.session_id": + x.SessionId = value.Interface().(string) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.amount": + x.Amount = value.Message().Interface().(*v1beta1.Coin) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.tokenomics.EventApplicationReimbursementRequest")) + } + panic(fmt.Errorf("message poktroll.tokenomics.EventApplicationReimbursementRequest 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_EventApplicationReimbursementRequest) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "poktroll.tokenomics.EventApplicationReimbursementRequest.amount": + if x.Amount == nil { + x.Amount = new(v1beta1.Coin) + } + return protoreflect.ValueOfMessage(x.Amount.ProtoReflect()) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.application_addr": + panic(fmt.Errorf("field application_addr of message poktroll.tokenomics.EventApplicationReimbursementRequest is not mutable")) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.service_id": + panic(fmt.Errorf("field service_id of message poktroll.tokenomics.EventApplicationReimbursementRequest is not mutable")) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.session_id": + panic(fmt.Errorf("field session_id of message poktroll.tokenomics.EventApplicationReimbursementRequest is not mutable")) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.tokenomics.EventApplicationReimbursementRequest")) + } + panic(fmt.Errorf("message poktroll.tokenomics.EventApplicationReimbursementRequest 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_EventApplicationReimbursementRequest) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "poktroll.tokenomics.EventApplicationReimbursementRequest.application_addr": + return protoreflect.ValueOfString("") + case "poktroll.tokenomics.EventApplicationReimbursementRequest.service_id": + return protoreflect.ValueOfString("") + case "poktroll.tokenomics.EventApplicationReimbursementRequest.session_id": + return protoreflect.ValueOfString("") + case "poktroll.tokenomics.EventApplicationReimbursementRequest.amount": + m := new(v1beta1.Coin) + return protoreflect.ValueOfMessage(m.ProtoReflect()) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.tokenomics.EventApplicationReimbursementRequest")) + } + panic(fmt.Errorf("message poktroll.tokenomics.EventApplicationReimbursementRequest 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_EventApplicationReimbursementRequest) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in poktroll.tokenomics.EventApplicationReimbursementRequest", 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_EventApplicationReimbursementRequest) 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_EventApplicationReimbursementRequest) 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_EventApplicationReimbursementRequest) 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_EventApplicationReimbursementRequest) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*EventApplicationReimbursementRequest) + 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.ApplicationAddr) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + l = len(x.ServiceId) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + l = len(x.SessionId) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + if x.Amount != nil { + l = options.Size(x.Amount) + 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().(*EventApplicationReimbursementRequest) + 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.Amount != nil { + encoded, err := options.Marshal(x.Amount) + 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] = 0x22 + } + if len(x.SessionId) > 0 { + i -= len(x.SessionId) + copy(dAtA[i:], x.SessionId) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.SessionId))) + i-- + dAtA[i] = 0x1a + } + if len(x.ServiceId) > 0 { + i -= len(x.ServiceId) + copy(dAtA[i:], x.ServiceId) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.ServiceId))) + i-- + dAtA[i] = 0x12 + } + if len(x.ApplicationAddr) > 0 { + i -= len(x.ApplicationAddr) + copy(dAtA[i:], x.ApplicationAddr) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.ApplicationAddr))) + 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().(*EventApplicationReimbursementRequest) + 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: EventApplicationReimbursementRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: EventApplicationReimbursementRequest: 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 ApplicationAddr", 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.ApplicationAddr = 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 ServiceId", 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.ServiceId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field SessionId", 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.SessionId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Amount", 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.Amount == nil { + x.Amount = &v1beta1.Coin{} + } + if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.Amount); err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := runtime.Skip(dAtA[iNdEx:]) + if err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if !options.DiscardUnknown { + x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + } + iNdEx += skippy + } + } + + if iNdEx > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil + } + return &protoiface.Methods{ + NoUnkeyedLiterals: struct{}{}, + Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, + Size: size, + Marshal: marshal, + Unmarshal: unmarshal, + Merge: nil, + CheckInitialized: nil, + } +} + // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.0 @@ -2703,16 +3330,77 @@ func (x *EventApplicationOverserviced) GetEffectiveBurn() *v1beta1.Coin { return nil } +// EventApplicationReimbursementRequest is emitted when an application requests a +// reimbursement +type EventApplicationReimbursementRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ApplicationAddr string `protobuf:"bytes,1,opt,name=application_addr,json=applicationAddr,proto3" json:"application_addr,omitempty"` + ServiceId string `protobuf:"bytes,2,opt,name=service_id,json=serviceId,proto3" json:"service_id,omitempty"` + SessionId string `protobuf:"bytes,3,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` + Amount *v1beta1.Coin `protobuf:"bytes,4,opt,name=amount,proto3" json:"amount,omitempty"` +} + +func (x *EventApplicationReimbursementRequest) Reset() { + *x = EventApplicationReimbursementRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_poktroll_tokenomics_event_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EventApplicationReimbursementRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EventApplicationReimbursementRequest) ProtoMessage() {} + +// Deprecated: Use EventApplicationReimbursementRequest.ProtoReflect.Descriptor instead. +func (*EventApplicationReimbursementRequest) Descriptor() ([]byte, []int) { + return file_poktroll_tokenomics_event_proto_rawDescGZIP(), []int{4} +} + +func (x *EventApplicationReimbursementRequest) GetApplicationAddr() string { + if x != nil { + return x.ApplicationAddr + } + return "" +} + +func (x *EventApplicationReimbursementRequest) GetServiceId() string { + if x != nil { + return x.ServiceId + } + return "" +} + +func (x *EventApplicationReimbursementRequest) GetSessionId() string { + if x != nil { + return x.SessionId + } + return "" +} + +func (x *EventApplicationReimbursementRequest) GetAmount() *v1beta1.Coin { + if x != nil { + return x.Amount + } + return nil +} + var File_poktroll_tokenomics_event_proto protoreflect.FileDescriptor var file_poktroll_tokenomics_event_proto_rawDesc = []byte{ 0x0a, 0x1f, 0x70, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x13, 0x70, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2e, 0x74, 0x6f, 0x6b, 0x65, - 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0x1a, 0x14, 0x67, 0x6f, 0x67, 0x6f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2f, 0x67, 0x6f, 0x67, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x63, 0x6f, - 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x62, 0x61, 0x73, 0x65, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2f, 0x63, 0x6f, 0x69, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1a, 0x70, 0x6f, + 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0x1a, 0x1e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x62, + 0x61, 0x73, 0x65, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x63, 0x6f, 0x69, 0x6e, + 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, 0x1a, 0x70, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x2f, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x70, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x2f, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, @@ -2785,25 +3473,37 @@ var file_poktroll_tokenomics_event_proto_rawDesc = []byte{ 0x75, 0x72, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x0d, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x42, - 0x75, 0x72, 0x6e, 0x2a, 0x60, 0x0a, 0x15, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x45, 0x78, 0x70, 0x69, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x1d, - 0x45, 0x58, 0x50, 0x49, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, - 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, - 0x11, 0x0a, 0x0d, 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4e, 0x47, - 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x49, 0x4e, 0x56, 0x41, - 0x4c, 0x49, 0x44, 0x10, 0x02, 0x42, 0xb8, 0x01, 0x0a, 0x17, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, - 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2e, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, - 0x73, 0x42, 0x0a, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, - 0x24, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, - 0x69, 0x2f, 0x70, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, - 0x6f, 0x6d, 0x69, 0x63, 0x73, 0xa2, 0x02, 0x03, 0x50, 0x54, 0x58, 0xaa, 0x02, 0x13, 0x50, 0x6f, - 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, - 0x73, 0xca, 0x02, 0x13, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x5c, 0x54, 0x6f, 0x6b, - 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0xe2, 0x02, 0x1f, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, - 0x6c, 0x6c, 0x5c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0x5c, 0x47, 0x50, - 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x14, 0x50, 0x6f, 0x6b, 0x74, - 0x72, 0x6f, 0x6c, 0x6c, 0x3a, 0x3a, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x75, 0x72, 0x6e, 0x22, 0xc2, 0x01, 0x0a, 0x24, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x41, 0x70, 0x70, + 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x69, 0x6d, 0x62, 0x75, 0x72, 0x73, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x10, + 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x64, 0x64, 0x72, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x31, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, + 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, + 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x2a, 0x60, 0x0a, 0x15, 0x43, 0x6c, 0x61, 0x69, + 0x6d, 0x45, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x61, 0x73, 0x6f, + 0x6e, 0x12, 0x21, 0x0a, 0x1d, 0x45, 0x58, 0x50, 0x49, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, + 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, + 0x45, 0x44, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x4d, 0x49, + 0x53, 0x53, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x52, 0x4f, 0x4f, 0x46, + 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x02, 0x42, 0xb8, 0x01, 0x0a, 0x17, 0x63, + 0x6f, 0x6d, 0x2e, 0x70, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2e, 0x74, 0x6f, 0x6b, 0x65, + 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0x42, 0x0a, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, + 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x24, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, + 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2f, + 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0xa2, 0x02, 0x03, 0x50, 0x54, 0x58, + 0xaa, 0x02, 0x13, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2e, 0x54, 0x6f, 0x6b, 0x65, + 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0xca, 0x02, 0x13, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, + 0x6c, 0x5c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0xe2, 0x02, 0x1f, 0x50, + 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x5c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, + 0x63, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, + 0x14, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x3a, 0x3a, 0x54, 0x6f, 0x6b, 0x65, 0x6e, + 0x6f, 0x6d, 0x69, 0x63, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2819,29 +3519,31 @@ func file_poktroll_tokenomics_event_proto_rawDescGZIP() []byte { } var file_poktroll_tokenomics_event_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_poktroll_tokenomics_event_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_poktroll_tokenomics_event_proto_msgTypes = make([]protoimpl.MessageInfo, 5) var file_poktroll_tokenomics_event_proto_goTypes = []interface{}{ - (ClaimExpirationReason)(0), // 0: poktroll.tokenomics.ClaimExpirationReason - (*EventClaimExpired)(nil), // 1: poktroll.tokenomics.EventClaimExpired - (*EventClaimSettled)(nil), // 2: poktroll.tokenomics.EventClaimSettled - (*EventRelayMiningDifficultyUpdated)(nil), // 3: poktroll.tokenomics.EventRelayMiningDifficultyUpdated - (*EventApplicationOverserviced)(nil), // 4: poktroll.tokenomics.EventApplicationOverserviced - (*proof.Claim)(nil), // 5: poktroll.proof.Claim - (proof.ProofRequirementReason)(0), // 6: poktroll.proof.ProofRequirementReason - (*v1beta1.Coin)(nil), // 7: cosmos.base.v1beta1.Coin + (ClaimExpirationReason)(0), // 0: poktroll.tokenomics.ClaimExpirationReason + (*EventClaimExpired)(nil), // 1: poktroll.tokenomics.EventClaimExpired + (*EventClaimSettled)(nil), // 2: poktroll.tokenomics.EventClaimSettled + (*EventRelayMiningDifficultyUpdated)(nil), // 3: poktroll.tokenomics.EventRelayMiningDifficultyUpdated + (*EventApplicationOverserviced)(nil), // 4: poktroll.tokenomics.EventApplicationOverserviced + (*EventApplicationReimbursementRequest)(nil), // 5: poktroll.tokenomics.EventApplicationReimbursementRequest + (*proof.Claim)(nil), // 6: poktroll.proof.Claim + (proof.ProofRequirementReason)(0), // 7: poktroll.proof.ProofRequirementReason + (*v1beta1.Coin)(nil), // 8: cosmos.base.v1beta1.Coin } var file_poktroll_tokenomics_event_proto_depIdxs = []int32{ - 5, // 0: poktroll.tokenomics.EventClaimExpired.claim:type_name -> poktroll.proof.Claim + 6, // 0: poktroll.tokenomics.EventClaimExpired.claim:type_name -> poktroll.proof.Claim 0, // 1: poktroll.tokenomics.EventClaimExpired.expiration_reason:type_name -> poktroll.tokenomics.ClaimExpirationReason - 5, // 2: poktroll.tokenomics.EventClaimSettled.claim:type_name -> poktroll.proof.Claim - 6, // 3: poktroll.tokenomics.EventClaimSettled.proof_requirement:type_name -> poktroll.proof.ProofRequirementReason - 7, // 4: poktroll.tokenomics.EventApplicationOverserviced.expected_burn:type_name -> cosmos.base.v1beta1.Coin - 7, // 5: poktroll.tokenomics.EventApplicationOverserviced.effective_burn:type_name -> cosmos.base.v1beta1.Coin - 6, // [6:6] is the sub-list for method output_type - 6, // [6:6] is the sub-list for method input_type - 6, // [6:6] is the sub-list for extension type_name - 6, // [6:6] is the sub-list for extension extendee - 0, // [0:6] is the sub-list for field type_name + 6, // 2: poktroll.tokenomics.EventClaimSettled.claim:type_name -> poktroll.proof.Claim + 7, // 3: poktroll.tokenomics.EventClaimSettled.proof_requirement:type_name -> poktroll.proof.ProofRequirementReason + 8, // 4: poktroll.tokenomics.EventApplicationOverserviced.expected_burn:type_name -> cosmos.base.v1beta1.Coin + 8, // 5: poktroll.tokenomics.EventApplicationOverserviced.effective_burn:type_name -> cosmos.base.v1beta1.Coin + 8, // 6: poktroll.tokenomics.EventApplicationReimbursementRequest.amount:type_name -> cosmos.base.v1beta1.Coin + 7, // [7:7] is the sub-list for method output_type + 7, // [7:7] 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 } func init() { file_poktroll_tokenomics_event_proto_init() } @@ -2898,6 +3600,18 @@ func file_poktroll_tokenomics_event_proto_init() { return nil } } + file_poktroll_tokenomics_event_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EventApplicationReimbursementRequest); 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{ @@ -2905,7 +3619,7 @@ func file_poktroll_tokenomics_event_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_poktroll_tokenomics_event_proto_rawDesc, NumEnums: 1, - NumMessages: 4, + NumMessages: 5, NumExtensions: 0, NumServices: 0, }, diff --git a/proto/poktroll/tokenomics/event.proto b/proto/poktroll/tokenomics/event.proto index 780564496..76ef86e5c 100644 --- a/proto/poktroll/tokenomics/event.proto +++ b/proto/poktroll/tokenomics/event.proto @@ -3,8 +3,8 @@ package poktroll.tokenomics; option go_package = "github.com/pokt-network/poktroll/x/tokenomics/types"; -import "gogoproto/gogo.proto"; import "cosmos/base/v1beta1/coin.proto"; +import "gogoproto/gogo.proto"; import "poktroll/proof/claim.proto"; import "poktroll/proof/requirement.proto"; @@ -51,3 +51,12 @@ message EventApplicationOverserviced { cosmos.base.v1beta1.Coin expected_burn = 2; cosmos.base.v1beta1.Coin effective_burn = 3; } + +// EventApplicationReimbursementRequest is emitted when an application requests a +// reimbursement +message EventApplicationReimbursementRequest { + string application_addr = 1; + string service_id = 2; + string session_id = 3; + cosmos.base.v1beta1.Coin amount = 4; +} diff --git a/x/tokenomics/keeper/token_logic_modules.go b/x/tokenomics/keeper/token_logic_modules.go index 74e6d66c3..0190d78b3 100644 --- a/x/tokenomics/keeper/token_logic_modules.go +++ b/x/tokenomics/keeper/token_logic_modules.go @@ -19,6 +19,7 @@ import ( "github.com/pokt-network/poktroll/telemetry" apptypes "github.com/pokt-network/poktroll/x/application/types" prooftypes "github.com/pokt-network/poktroll/x/proof/types" + sessiontypes "github.com/pokt-network/poktroll/x/session/types" sharedtypes "github.com/pokt-network/poktroll/x/shared/types" suppliertypes "github.com/pokt-network/poktroll/x/supplier/types" tokenomicstypes "github.com/pokt-network/poktroll/x/tokenomics/types" @@ -26,29 +27,46 @@ import ( ) const ( + // Governance parameters for the TLMGlobalMint module + // TODO_UPNEXT(@olshansk): Remove this. An ephemeral placeholder before + // real values are introduced. When this is changed to a governance param, + // make sure to also add the necessary unit tests. + MintGlobalInflation = 0.0000000 // TODO_UPNEXT(@olshansk): Make all of the governance params MintAllocationDAO = 0.1 MintAllocationProposer = 0.05 MintAllocationSupplier = 0.7 MintAllocationSourceOwner = 0.15 MintAllocationApplication = 0.0 - // TODO_UPNEXT(@olshansk): Remove this. An ephemeral placeholder before - // real values are introduced. When this is changed to a governance param, - // make sure to also add the necessary unit tests. - MintGlobalAllocation = 0.0000000 ) type TokenLogicModule int const ( + // TLMRelayBurnEqualsMint is the token logic module that burns the application's + // stake based on the amount of work done by the supplier. The same amount of + // tokens is minted and sent to the supplier. + // When the network achieves equilibrium, this is theoretically the only TLM that will be necessary. TLMRelayBurnEqualsMint TokenLogicModule = iota + + // TLMGlobalMint is the token logic module that mints new tokens based on the + // on global governance parameters in order to reward the participants providing + // services while keeping inflation in check. TLMGlobalMint - // TODO_UPNEXT(@olshansk): Add more TLMs + + // TLMGlobalMintReimbursementRequest is the token logic module that complements + // TLMGlobalMint to enable permissionless demand. In order to prevent self-dealing + // attacks, applications will be overcharged by the amount equal to global inflation, + // those funds will be sent to the DAO/PNF, and event will be emitted to be used + // for reimbursements. + // TODO_POST_MAINNET: Introduce proper tokenomics based on the research done by @rawthil and @shane. + TLMGlobalMintReimbursementRequest ) var tokenLogicModuleStrings = [...]string{ "TLMRelayBurnEqualsMint", "TLMGlobalMint", + "TLMGlobalMintReimbursementRequest", } func (tlm TokenLogicModule) String() string { @@ -69,6 +87,7 @@ type TokenLogicModuleProcessor func( Keeper, context.Context, *sharedtypes.Service, + *sessiontypes.SessionHeader, *apptypes.Application, *sharedtypes.Supplier, cosmostypes.Coin, @@ -245,6 +264,7 @@ func (k Keeper) ProcessTokenLogicModules( func (k Keeper) TokenLogicModuleRelayBurnEqualsMint( ctx context.Context, service *sharedtypes.Service, + _ *sessiontypes.SessionHeader, application *apptypes.Application, supplier *sharedtypes.Supplier, settlementCoin cosmostypes.Coin, @@ -319,24 +339,19 @@ func (k Keeper) TokenLogicModuleRelayBurnEqualsMint( } // TokenLogicModuleGlobalMint processes the business logic for the GlobalMint TLM. -// TODO_UPNEXT(@olshansk): Delete this in favor of a real TLM that mints tokens -// and distributes them to the appropriate accounts via boosts. func (k Keeper) TokenLogicModuleGlobalMint( ctx context.Context, service *sharedtypes.Service, + _ *sessiontypes.SessionHeader, application *apptypes.Application, supplier *sharedtypes.Supplier, - settlementCoins cosmostypes.Coin, + settlementCoin cosmostypes.Coin, relayMiningDifficulty *tokenomictypes.RelayMiningDifficulty, ) error { logger := k.Logger().With("method", "TokenLogicModuleGlobalMint") // Determine how much new uPOKT to mint based on global inflation - // TODO_MAINNET: Consider using fixed point arithmetic for deterministic results. - settlementAmtFloat := new(big.Float).SetUint64(settlementCoins.Amount.Uint64()) - newMintAmtFloat := new(big.Float).Mul(settlementAmtFloat, big.NewFloat(MintGlobalAllocation)) - newMintAmtInt, _ := newMintAmtFloat.Int64() - newMintCoins := sdk.NewCoins(cosmostypes.NewCoin(volatile.DenomuPOKT, math.NewInt(newMintAmtInt))) + newMintCoins, newMintAmtFloat := calculateGlobalMintAllocationFromSettlementAmount(settlementCoin) // Mint new uPOKT to the tokenomics module account if err := k.bankKeeper.MintCoins(ctx, tokenomictypes.ModuleName, newMintCoins); err != nil { @@ -353,15 +368,16 @@ func (k Keeper) TokenLogicModuleGlobalMint( logger.Debug(fmt.Sprintf("sent (%v) newley minted coins from the tokenomics module to the application with address %q", appCoin, application.Address)) // Send a portion of the rewards to the supplier shareholders. - coinsToShareAmt := calculateGlobalMintAllocationFromSettlementAmount(newMintAmtFloat, MintAllocationSupplier) - if err = k.distributeSupplierRewardsToShareHolders(ctx, supplier.OperatorAddress, service.Id, uint64(coinsToShareAmt)); err != nil { + supplierCoinsToShareAmt := calculateAllocationAmount(newMintAmtFloat, MintAllocationSupplier) + supplierCoin := cosmostypes.NewCoin(volatile.DenomuPOKT, math.NewInt(supplierCoinsToShareAmt)) + if err = k.distributeSupplierRewardsToShareHolders(ctx, supplier.OperatorAddress, service.Id, uint64(supplierCoinsToShareAmt)); err != nil { return tokenomicstypes.ErrTokenomicsSupplierModuleMintFailed.Wrapf( "distributing rewards to supplier with operator address %s shareholders: %v", supplier.OperatorAddress, err, ) } - supplierCoin := cosmostypes.NewCoin(volatile.DenomuPOKT, math.NewInt(newMintAmtInt)) + logger.Debug(fmt.Sprintf("sent (%v) newley minted coins from the tokenomics module to the supplier with address %q", supplierCoin, supplier.OperatorAddress)) // Send a portion of the rewards to the DAO @@ -386,16 +402,73 @@ func (k Keeper) TokenLogicModuleGlobalMint( } logger.Debug(fmt.Sprintf("sent (%v) newley minted coins from the tokenomics module to the proposer with address %q", proposerCoin, proposerAddr)) - // TODO_MAINNET: Verify that the total distributed coins equals the settlement coins which could happen due to float rounding + // Check and log the total amount of coins distributed totalDistributedCoins := appCoin.Add(supplierCoin).Add(*daoCoin).Add(*serviceCoin).Add(*proposerCoin) - if totalDistributedCoins.Amount.BigInt().Cmp(settlementCoins.Amount.BigInt()) != 0 { - logger.Error(fmt.Sprintf("TODO_MAINNET: The total distributed coins (%v) does not equal the settlement coins (%v)", totalDistributedCoins, settlementCoins.Amount.BigInt())) + if totalDistributedCoins.Amount.BigInt().Cmp(settlementCoin.Amount.BigInt()) != 0 { + logger.Error(fmt.Sprintf("TODO_MAINNET: Verify why the total distributed coins (%v) do not equal the settlement coins (%v). Likely floating point arithmetic.", totalDistributedCoins, settlementCoin.Amount.BigInt())) } logger.Info(fmt.Sprintf("distributed (%v) coins to the application, supplier, DAO, source owner, and proposer", totalDistributedCoins)) return nil } +// 1. Mint = Burn +// 2. Global Mint +// 4. Overcharge applications +// - Determine the amount send to suppliers +// - Determine the amount send to source owner +// - Overcharge application based on the sum of the two above +// - Send the overcharge to the PNF +// - Emit an event so we can track it +// - PNF manually reimburses the application at the end of the month +// - Prevents self dealing because application has to ask for reimbursement +// - Does not introduce friction to service owners getting rewarded +// - Does not introduce friction to suppliers getting rewarded +// - Ensure NewSession breaks if app stake is too low +// - Ensure relayminer has a toggle to prevent over charging +func (k Keeper) TokenLogicModuleGlobalMintReimbursementRequest( + ctx context.Context, + service *sharedtypes.Service, + sessionHeader *sessiontypes.SessionHeader, + application *apptypes.Application, + supplier *sharedtypes.Supplier, + settlementCoins cosmostypes.Coin, + relayMiningDifficulty *tokenomictypes.RelayMiningDifficulty, +) error { + logger := k.Logger().With("method", "TokenLogicModuleGlobalMint") + + // Determine how much new uPOKT to mint based on global inflation + newMintCoins, _ := calculateGlobalMintAllocationFromSettlementAmount(settlementCoins) + + + + // EventApplicationReimbursementRequest + reimbursementRequest := tokenomictypes.EventApplicationReimbursementRequest{ + ApplicationAddr: application.Address, + ServiceId: service.Id, + SessionId: sessionHeader.SessionId, + Amount: &newMintCoins[0], + } + + eventManager := cosmostypes.UnwrapSDKContext(ctx).EventManager() + if err := eventManager.EmitTypedEvent(&reimbursementRequest); err != nil { + return tokenomicstypes.ErrTokenomicsApplicationReimbursementRequestFailed.Wrapf( + "application address: %s; service Id %s; session Id: %s; amount: %s", + application.GetAddress(), + service.Id, + sessionHeader.SessionId, + newMintCoins.String(), + ) + } + + // EventApplicationReimbursementRequest + // What if the application is overcharged? + // How do I enforce running both of them? + // Need to add a new governance parameter? + // Should we prevent new application sessions from starting if its too low? + return nil +} + // sendRewardsToAccount sends (settlementAmtFloat * allocation) tokens from the // tokenomics module account to the specified address. func (k Keeper) sendRewardsToAccount( @@ -411,7 +484,7 @@ func (k Keeper) sendRewardsToAccount( return nil, err } - coinsToAccAmt := calculateGlobalMintAllocationFromSettlementAmount(settlementAmtFloat, allocation) + coinsToAccAmt := calculateAllocationAmount(settlementAmtFloat, allocation) coinToAcc := cosmostypes.NewCoin(volatile.DenomuPOKT, math.NewInt(coinsToAccAmt)) if err := k.bankKeeper.SendCoinsFromModuleToAccount( ctx, suppliertypes.ModuleName, accountAddr, sdk.NewCoins(coinToAcc), @@ -454,12 +527,13 @@ func (k Keeper) handleOverservicedApplication( } eventManager := cosmostypes.UnwrapSDKContext(ctx).EventManager() if err := eventManager.EmitTypedEvent(applicationOverservicedEvent); err != nil { - return cosmostypes.Coin{}, tokenomicstypes.ErrTokenomicsApplicationOverserviced.Wrapf( - "application address: %s; expected burn %s; effective burn: %s", - application.GetAddress(), - expectedBurn.String(), - application.GetStake().String(), - ) + return cosmostypes.Coin{}, + tokenomicstypes.ErrTokenomicsApplicationOverservicedEvent.Wrapf( + "application address: %s; expected burn %s; effective burn: %s", + application.GetAddress(), + expectedBurn.String(), + application.GetStake().String(), + ) } return *application.Stake, nil } @@ -518,6 +592,7 @@ func (k Keeper) distributeSupplierRewardsToShareHolders( shareAmountMap := GetShareAmountMap(serviceRevShare, amountToDistribute) for shareHolderAddress, shareAmount := range shareAmountMap { + // TODO_IN_THIS_PR: Why don't we use sendRewardsToAccount here? shareAmountCoin := cosmostypes.NewCoin(volatile.DenomuPOKT, math.NewInt(int64(shareAmount))) shareAmountCoins := cosmostypes.NewCoins(shareAmountCoin) shareHolderAccAddress, err := sdk.AccAddressFromBech32(shareHolderAddress) @@ -541,14 +616,26 @@ func (k Keeper) distributeSupplierRewardsToShareHolders( return nil } -// calculateGlobalMintAllocationFromSettlementAmount calculates the global mint -// allocation resulting from the GlobalMint TLM given the settlement amount and -// the allocation percentage. -func calculateGlobalMintAllocationFromSettlementAmount( - settlementAmtFloat *big.Float, - allocation float64, +// calculateGlobalMintAllocationFromSettlementAmount calculates the amount of uPOKT +// to mint based on the global inflation rate as a function of the settlement amount +// for a particular claim(s) or session(s). +func calculateGlobalMintAllocationFromSettlementAmount(settlementCoin sdk.Coin) (sdk.Coins, *big.Float) { + // Determine how much new uPOKT to mint based on global inflation + // TODO_MAINNET: Consider using fixed point arithmetic for deterministic results. + settlementAmtFloat := new(big.Float).SetUint64(settlementCoin.Amount.Uint64()) + newMintAmtFloat := new(big.Float).Mul(settlementAmtFloat, big.NewFloat(MintGlobalInflation)) + newMintAmtInt, _ := newMintAmtFloat.Int64() + mintAmtCoins := sdk.NewCoins(cosmostypes.NewCoin(volatile.DenomuPOKT, math.NewInt(newMintAmtInt))) + return mintAmtCoins, newMintAmtFloat +} + +// calculateAllocationAmount does big float arithmetic to determine the absolute +// amount from amountFloat based on the allocation percentage provided. +func calculateAllocationAmount( + amountFloat *big.Float, + allocationPercentage float64, ) int64 { - coinsToAccAmt, _ := big.NewFloat(0).Mul(settlementAmtFloat, big.NewFloat(allocation)).Int64() + coinsToAccAmt, _ := big.NewFloat(0).Mul(amountFloat, big.NewFloat(allocationPercentage)).Int64() return coinsToAccAmt } @@ -563,12 +650,12 @@ func GetShareAmountMap( ) (shareAmountMap map[string]uint64) { totalDistributed := uint64(0) shareAmountMap = make(map[string]uint64, len(serviceRevShare)) - for _, revshare := range serviceRevShare { + for _, revShare := range serviceRevShare { // TODO_MAINNET: Consider using fixed point arithmetic for deterministic results. - sharePercentageFloat := big.NewFloat(float64(revshare.RevSharePercentage) / 100) + sharePercentageFloat := big.NewFloat(float64(revShare.RevSharePercentage) / 100) amountToDistributeFloat := big.NewFloat(float64(amountToDistribute)) shareAmount, _ := big.NewFloat(0).Mul(amountToDistributeFloat, sharePercentageFloat).Uint64() - shareAmountMap[revshare.Address] = shareAmount + shareAmountMap[revShare.Address] = shareAmount totalDistributed += shareAmount } diff --git a/x/tokenomics/types/errors.go b/x/tokenomics/types/errors.go index 3ff72fc5a..6e7c23a0d 100644 --- a/x/tokenomics/types/errors.go +++ b/x/tokenomics/types/errors.go @@ -6,30 +6,31 @@ import sdkerrors "cosmossdk.io/errors" // x/tokenomics module sentinel errors var ( - ErrTokenomicsInvalidSigner = sdkerrors.Register(ModuleName, 1100, "the provided authority address does not match the on-chain governance address") - ErrTokenomicsAddressInvalid = sdkerrors.Register(ModuleName, 1101, "the provided authority address is not a valid bech32 address") - ErrTokenomicsClaimNil = sdkerrors.Register(ModuleName, 1102, "provided claim is nil") - ErrTokenomicsSessionHeaderNil = sdkerrors.Register(ModuleName, 1103, "provided claim's session header is nil") - ErrTokenomicsSessionHeaderInvalid = sdkerrors.Register(ModuleName, 1104, "provided claim's session header is invalid") - ErrTokenomicsSupplierModuleSendFailed = sdkerrors.Register(ModuleName, 1105, "failed to send uPOKT to supplier module account") - ErrTokenomicsSupplierOperatorAddressInvalid = sdkerrors.Register(ModuleName, 1106, "the supplier operator address in the claim is not a valid bech32 address") - ErrTokenomicsSupplierNotFound = sdkerrors.Register(ModuleName, 1107, "supplier not found") - ErrTokenomicsApplicationNotFound = sdkerrors.Register(ModuleName, 1108, "application not found") - ErrTokenomicsApplicationModuleBurn = sdkerrors.Register(ModuleName, 1109, "failed to burn uPOKT from application module account") - ErrTokenomicsApplicationAddressInvalid = sdkerrors.Register(ModuleName, 1110, "the application address in the claim is not a valid bech32 address") - ErrTokenomicsParamsInvalid = sdkerrors.Register(ModuleName, 1111, "provided params are invalid") - ErrTokenomicsRootHashInvalid = sdkerrors.Register(ModuleName, 1112, "the root hash in the claim is invalid") - ErrTokenomicsApplicationNewStakeInvalid = sdkerrors.Register(ModuleName, 1113, "application stake cannot be reduced to a -ve amount") - ErrTokenomicsParamNameInvalid = sdkerrors.Register(ModuleName, 1114, "the provided param name is invalid") - ErrTokenomicsParamInvalid = sdkerrors.Register(ModuleName, 1115, "the provided param is invalid") - ErrTokenomicsUnmarshalInvalid = sdkerrors.Register(ModuleName, 1116, "failed to unmarshal the provided bytes") - ErrTokenomicsDuplicateIndex = sdkerrors.Register(ModuleName, 1117, "cannot have a duplicate index") - ErrTokenomicsMissingRelayMiningDifficulty = sdkerrors.Register(ModuleName, 1118, "missing relay mining difficulty") - ErrTokenomicsApplicationOverserviced = sdkerrors.Register(ModuleName, 1119, "application was overserviced") - ErrTokenomicsServiceNotFound = sdkerrors.Register(ModuleName, 1120, "service not found") - ErrTokenomicsModuleMintFailed = sdkerrors.Register(ModuleName, 1121, "failed to mint uPOKT to tokenomics module account") - ErrTokenomicsSendingMintRewards = sdkerrors.Register(ModuleName, 1122, "failed to send minted rewards") - ErrTokenomicsSupplierModuleMintFailed = sdkerrors.Register(ModuleName, 1123, "failed to mint uPOKT to supplier module account") - ErrTokenomicsSupplierOwnerAddressInvalid = sdkerrors.Register(ModuleName, 1124, "the supplier owner address in the claim is not a valid bech32 address") - ErrTokenomicsSupplierRevShareFailed = sdkerrors.Register(ModuleName, 1125, "failed to send rev share to supplier shareholders") + ErrTokenomicsInvalidSigner = sdkerrors.Register(ModuleName, 1100, "the provided authority address does not match the on-chain governance address") + ErrTokenomicsAddressInvalid = sdkerrors.Register(ModuleName, 1101, "the provided authority address is not a valid bech32 address") + ErrTokenomicsClaimNil = sdkerrors.Register(ModuleName, 1102, "provided claim is nil") + ErrTokenomicsSessionHeaderNil = sdkerrors.Register(ModuleName, 1103, "provided claim's session header is nil") + ErrTokenomicsSessionHeaderInvalid = sdkerrors.Register(ModuleName, 1104, "provided claim's session header is invalid") + ErrTokenomicsSupplierModuleSendFailed = sdkerrors.Register(ModuleName, 1105, "failed to send uPOKT to supplier module account") + ErrTokenomicsSupplierOperatorAddressInvalid = sdkerrors.Register(ModuleName, 1106, "the supplier operator address in the claim is not a valid bech32 address") + ErrTokenomicsSupplierNotFound = sdkerrors.Register(ModuleName, 1107, "supplier not found") + ErrTokenomicsApplicationNotFound = sdkerrors.Register(ModuleName, 1108, "application not found") + ErrTokenomicsApplicationModuleBurn = sdkerrors.Register(ModuleName, 1109, "failed to burn uPOKT from application module account") + ErrTokenomicsApplicationAddressInvalid = sdkerrors.Register(ModuleName, 1110, "the application address in the claim is not a valid bech32 address") + ErrTokenomicsParamsInvalid = sdkerrors.Register(ModuleName, 1111, "provided params are invalid") + ErrTokenomicsRootHashInvalid = sdkerrors.Register(ModuleName, 1112, "the root hash in the claim is invalid") + ErrTokenomicsApplicationNewStakeInvalid = sdkerrors.Register(ModuleName, 1113, "application stake cannot be reduced to a -ve amount") + ErrTokenomicsParamNameInvalid = sdkerrors.Register(ModuleName, 1114, "the provided param name is invalid") + ErrTokenomicsParamInvalid = sdkerrors.Register(ModuleName, 1115, "the provided param is invalid") + ErrTokenomicsUnmarshalInvalid = sdkerrors.Register(ModuleName, 1116, "failed to unmarshal the provided bytes") + ErrTokenomicsDuplicateIndex = sdkerrors.Register(ModuleName, 1117, "cannot have a duplicate index") + ErrTokenomicsMissingRelayMiningDifficulty = sdkerrors.Register(ModuleName, 1118, "missing relay mining difficulty") + ErrTokenomicsApplicationOverservicedEvent = sdkerrors.Register(ModuleName, 1119, "application overserviced event cannot be sent") + ErrTokenomicsServiceNotFound = sdkerrors.Register(ModuleName, 1120, "service not found") + ErrTokenomicsModuleMintFailed = sdkerrors.Register(ModuleName, 1121, "failed to mint uPOKT to tokenomics module account") + ErrTokenomicsSendingMintRewards = sdkerrors.Register(ModuleName, 1122, "failed to send minted rewards") + ErrTokenomicsSupplierModuleMintFailed = sdkerrors.Register(ModuleName, 1123, "failed to mint uPOKT to supplier module account") + ErrTokenomicsSupplierOwnerAddressInvalid = sdkerrors.Register(ModuleName, 1124, "the supplier owner address in the claim is not a valid bech32 address") + ErrTokenomicsSupplierRevShareFailed = sdkerrors.Register(ModuleName, 1125, "failed to send rev share to supplier shareholders") + ErrTokenomicsApplicationReimbursementRequestFailed = sdkerrors.Register(ModuleName, 1126, "failed to send application reimbursement request event") ) diff --git a/x/tokenomics/types/event.pb.go b/x/tokenomics/types/event.pb.go index 5c55fbc6e..945d4ab97 100644 --- a/x/tokenomics/types/event.pb.go +++ b/x/tokenomics/types/event.pb.go @@ -335,63 +335,138 @@ func (m *EventApplicationOverserviced) GetEffectiveBurn() *types1.Coin { return nil } +// EventApplicationReimbursementRequest is emitted when an application requests a +// reimbursement +type EventApplicationReimbursementRequest struct { + ApplicationAddr string `protobuf:"bytes,1,opt,name=application_addr,json=applicationAddr,proto3" json:"application_addr,omitempty"` + ServiceId string `protobuf:"bytes,2,opt,name=service_id,json=serviceId,proto3" json:"service_id,omitempty"` + SessionId string `protobuf:"bytes,3,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` + Amount *types1.Coin `protobuf:"bytes,4,opt,name=amount,proto3" json:"amount,omitempty"` +} + +func (m *EventApplicationReimbursementRequest) Reset() { *m = EventApplicationReimbursementRequest{} } +func (m *EventApplicationReimbursementRequest) String() string { return proto.CompactTextString(m) } +func (*EventApplicationReimbursementRequest) ProtoMessage() {} +func (*EventApplicationReimbursementRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_a78874bbf91a58c7, []int{4} +} +func (m *EventApplicationReimbursementRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EventApplicationReimbursementRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EventApplicationReimbursementRequest.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 *EventApplicationReimbursementRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_EventApplicationReimbursementRequest.Merge(m, src) +} +func (m *EventApplicationReimbursementRequest) XXX_Size() int { + return m.Size() +} +func (m *EventApplicationReimbursementRequest) XXX_DiscardUnknown() { + xxx_messageInfo_EventApplicationReimbursementRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_EventApplicationReimbursementRequest proto.InternalMessageInfo + +func (m *EventApplicationReimbursementRequest) GetApplicationAddr() string { + if m != nil { + return m.ApplicationAddr + } + return "" +} + +func (m *EventApplicationReimbursementRequest) GetServiceId() string { + if m != nil { + return m.ServiceId + } + return "" +} + +func (m *EventApplicationReimbursementRequest) GetSessionId() string { + if m != nil { + return m.SessionId + } + return "" +} + +func (m *EventApplicationReimbursementRequest) GetAmount() *types1.Coin { + if m != nil { + return m.Amount + } + return nil +} + func init() { proto.RegisterEnum("poktroll.tokenomics.ClaimExpirationReason", ClaimExpirationReason_name, ClaimExpirationReason_value) proto.RegisterType((*EventClaimExpired)(nil), "poktroll.tokenomics.EventClaimExpired") proto.RegisterType((*EventClaimSettled)(nil), "poktroll.tokenomics.EventClaimSettled") proto.RegisterType((*EventRelayMiningDifficultyUpdated)(nil), "poktroll.tokenomics.EventRelayMiningDifficultyUpdated") proto.RegisterType((*EventApplicationOverserviced)(nil), "poktroll.tokenomics.EventApplicationOverserviced") + proto.RegisterType((*EventApplicationReimbursementRequest)(nil), "poktroll.tokenomics.EventApplicationReimbursementRequest") } func init() { proto.RegisterFile("poktroll/tokenomics/event.proto", fileDescriptor_a78874bbf91a58c7) } var fileDescriptor_a78874bbf91a58c7 = []byte{ - // 718 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x54, 0xc1, 0x4e, 0xdb, 0x4a, - 0x14, 0x8d, 0x03, 0x3c, 0x29, 0xc3, 0x03, 0x12, 0x53, 0xd4, 0x94, 0x42, 0x12, 0xb2, 0xa8, 0x28, + // 776 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x55, 0xcd, 0x4e, 0xeb, 0x46, + 0x14, 0x8e, 0xc3, 0x8f, 0x94, 0xa1, 0x40, 0x32, 0x14, 0x35, 0xa5, 0x90, 0x84, 0xa8, 0xaa, 0x28, 0x15, 0xb6, 0x00, 0xa9, 0xab, 0x0a, 0x35, 0x09, 0xa6, 0x58, 0x2a, 0x49, 0xe4, 0x40, 0x55, 0x75, - 0x33, 0x75, 0xec, 0x9b, 0x64, 0x4a, 0x3c, 0xe3, 0x8e, 0xc7, 0x49, 0xf8, 0x8b, 0x7e, 0x40, 0x7f, - 0xa0, 0x8b, 0xfe, 0x47, 0xa5, 0x6e, 0x58, 0x76, 0x85, 0x2a, 0xd8, 0xf1, 0x15, 0x95, 0xc7, 0x21, - 0x49, 0x03, 0x55, 0xd7, 0xdd, 0x24, 0xd6, 0x3d, 0xe7, 0xdc, 0x7b, 0xe6, 0x78, 0x7c, 0x51, 0xde, - 0x67, 0x67, 0x82, 0xb3, 0x6e, 0x57, 0x17, 0xec, 0x0c, 0x28, 0xf3, 0x88, 0x13, 0xe8, 0xd0, 0x03, - 0x2a, 0x34, 0x9f, 0x33, 0xc1, 0xd4, 0xe5, 0x5b, 0x82, 0x36, 0x26, 0xac, 0x3e, 0x68, 0xb3, 0x36, - 0x93, 0xb8, 0x1e, 0x3d, 0xc5, 0xd4, 0xd5, 0x9c, 0xc3, 0x02, 0x8f, 0x05, 0x7a, 0xd3, 0x0e, 0x40, - 0xef, 0xed, 0x34, 0x41, 0xd8, 0x3b, 0xba, 0xc3, 0x08, 0x1d, 0xe2, 0xab, 0xa3, 0x59, 0x3e, 0x67, - 0xac, 0xa5, 0x3b, 0x5d, 0x9b, 0x78, 0x43, 0xac, 0x30, 0x85, 0x71, 0xf8, 0x18, 0x12, 0x0e, 0xde, - 0xc8, 0x48, 0xf1, 0x6b, 0x12, 0x65, 0x8c, 0xc8, 0x58, 0x25, 0x92, 0x19, 0x03, 0x9f, 0x70, 0x70, - 0xd5, 0xe7, 0x68, 0x4e, 0xb6, 0xc9, 0x2a, 0x05, 0x65, 0x73, 0x7e, 0x77, 0x45, 0x1b, 0xd9, 0x95, - 0x7d, 0x34, 0x49, 0x2e, 0xa7, 0x6e, 0x2e, 0xf3, 0x31, 0xcf, 0x8a, 0xff, 0xd4, 0x6d, 0x84, 0x68, - 0xe8, 0x61, 0x0e, 0x5d, 0xfb, 0x3c, 0xc8, 0x26, 0x0b, 0xca, 0xe6, 0x6c, 0x79, 0xf1, 0xe6, 0x32, - 0x3f, 0x51, 0xb5, 0x52, 0x34, 0xf4, 0x2c, 0xf9, 0xa8, 0x96, 0x50, 0x26, 0x02, 0x1c, 0xe6, 0xf9, - 0xa1, 0x00, 0x1c, 0x52, 0x22, 0x82, 0xec, 0x8c, 0x54, 0xad, 0xdc, 0x5c, 0xe6, 0xef, 0x82, 0xd6, - 0x12, 0x0d, 0xbd, 0x4a, 0x5c, 0x39, 0x8d, 0x0a, 0x2a, 0x45, 0x19, 0x88, 0x4c, 0xdb, 0x82, 0x30, - 0x8a, 0x39, 0xd8, 0x01, 0xa3, 0xd9, 0xd9, 0x82, 0xb2, 0xb9, 0xb8, 0xbb, 0xa5, 0xdd, 0x13, 0xb2, - 0x36, 0x3e, 0xa7, 0x94, 0x58, 0x52, 0x11, 0x8f, 0xbb, 0xd3, 0xc8, 0x4a, 0xc3, 0x14, 0xb1, 0xf8, - 0xe5, 0xb7, 0xbc, 0x1a, 0x20, 0x44, 0xf7, 0x9f, 0xca, 0xeb, 0x03, 0xca, 0x48, 0x4b, 0x78, 0xe2, - 0x2a, 0x0c, 0xf3, 0x7a, 0x32, 0xed, 0xba, 0x1e, 0xfd, 0x5a, 0x63, 0xde, 0x64, 0x56, 0x77, 0x9a, - 0x58, 0x69, 0x7f, 0x8a, 0x5e, 0xfc, 0x9c, 0x44, 0x1b, 0x32, 0x2b, 0x69, 0xff, 0x98, 0x50, 0x42, - 0xdb, 0x07, 0xa4, 0xd5, 0x22, 0x4e, 0xd8, 0x15, 0xe7, 0xa7, 0xbe, 0x6b, 0x0b, 0x70, 0xd5, 0x75, - 0x84, 0x02, 0xe0, 0x3d, 0xe2, 0x00, 0x26, 0xae, 0x0c, 0x30, 0x65, 0xa5, 0x86, 0x15, 0xd3, 0x55, - 0xf7, 0xd1, 0x9a, 0xcf, 0xa1, 0x87, 0x85, 0xcd, 0xdb, 0x20, 0x70, 0xc7, 0x0e, 0x3a, 0xb8, 0x03, - 0x03, 0x0c, 0xd4, 0x61, 0x2e, 0xb8, 0x32, 0xb4, 0x94, 0x95, 0x8d, 0x38, 0x27, 0x92, 0x72, 0x64, - 0x07, 0x9d, 0x23, 0x18, 0x18, 0x31, 0xae, 0xbe, 0x40, 0x8f, 0x29, 0xf4, 0xff, 0x28, 0x9f, 0x91, - 0xf2, 0x87, 0x14, 0xfa, 0xf7, 0xaa, 0xb7, 0xd1, 0xb2, 0x9c, 0x3e, 0x7e, 0x1f, 0x18, 0x3c, 0x5b, - 0x06, 0x36, 0x1b, 0x9d, 0x18, 0x7a, 0xd5, 0xdb, 0xb7, 0x63, 0x78, 0xb6, 0xfa, 0x0c, 0xa9, 0xd1, - 0xb0, 0x29, 0xf6, 0x9c, 0x64, 0x2f, 0x51, 0xe8, 0x4f, 0x92, 0x8b, 0xdf, 0x15, 0xb4, 0x26, 0xe3, - 0x29, 0xf9, 0x7e, 0x97, 0x38, 0xf2, 0x96, 0xd5, 0x7a, 0xc0, 0x87, 0x67, 0x77, 0xd5, 0xa7, 0x28, - 0x6d, 0x8f, 0x21, 0x6c, 0xbb, 0x2e, 0x1f, 0xe6, 0xb3, 0x34, 0x51, 0x2f, 0xb9, 0x2e, 0x57, 0xf7, - 0xd1, 0x02, 0x0c, 0x7c, 0x70, 0x04, 0xb8, 0xb8, 0x19, 0x72, 0x2a, 0x63, 0x99, 0xdf, 0x7d, 0xa4, - 0xc5, 0xcb, 0x43, 0x8b, 0x96, 0x87, 0x36, 0x5c, 0x1e, 0x5a, 0x85, 0x11, 0x6a, 0xfd, 0x7f, 0xcb, - 0x2f, 0x87, 0x9c, 0xaa, 0x2f, 0xd1, 0x22, 0xb4, 0x5a, 0xe0, 0x08, 0xd2, 0x83, 0xb8, 0xc1, 0xcc, - 0xdf, 0x1a, 0x2c, 0x8c, 0x04, 0x51, 0x87, 0xad, 0xf7, 0x68, 0xe5, 0xde, 0x4f, 0x4b, 0xdd, 0x40, - 0xeb, 0xc6, 0xdb, 0xba, 0x69, 0x95, 0x4e, 0xcc, 0x5a, 0x15, 0x5b, 0x46, 0xa9, 0x51, 0xab, 0xe2, - 0xd3, 0x6a, 0xa3, 0x6e, 0x54, 0xcc, 0x43, 0xd3, 0x38, 0x48, 0x27, 0xd4, 0x0c, 0x5a, 0xa8, 0x5b, - 0xb5, 0xda, 0x21, 0x3e, 0x36, 0x1b, 0x0d, 0xb3, 0xfa, 0x2a, 0xad, 0x8c, 0x4b, 0x66, 0xf5, 0x4d, - 0xe9, 0xb5, 0x79, 0x90, 0x4e, 0x96, 0x8f, 0xbf, 0x5d, 0xe5, 0x94, 0x8b, 0xab, 0x9c, 0xf2, 0xf3, - 0x2a, 0xa7, 0x7c, 0xba, 0xce, 0x25, 0x2e, 0xae, 0x73, 0x89, 0x1f, 0xd7, 0xb9, 0xc4, 0xbb, 0xbd, - 0x36, 0x11, 0x9d, 0xb0, 0xa9, 0x39, 0xcc, 0xd3, 0xa3, 0x3b, 0xbc, 0x4d, 0x41, 0xf4, 0x19, 0x3f, - 0xd3, 0x47, 0xeb, 0x6f, 0x30, 0xb9, 0x88, 0xc5, 0xb9, 0x0f, 0x41, 0xf3, 0x3f, 0xb9, 0x00, 0xf7, - 0x7e, 0x05, 0x00, 0x00, 0xff, 0xff, 0xac, 0x71, 0x68, 0xf9, 0xac, 0x05, 0x00, 0x00, + 0xe3, 0x3a, 0xf6, 0x49, 0x32, 0x25, 0x9e, 0x31, 0xe3, 0x71, 0x12, 0xde, 0xa2, 0x0f, 0xd0, 0x17, + 0xe8, 0xa2, 0x2f, 0xd1, 0x55, 0xa5, 0x6e, 0x58, 0x76, 0x85, 0x2a, 0xd8, 0xf1, 0x14, 0x57, 0x1e, + 0x3b, 0x3f, 0x04, 0xee, 0xbd, 0xba, 0xcb, 0xbb, 0x49, 0x46, 0xe7, 0x7c, 0xdf, 0x37, 0xe7, 0x7c, + 0x73, 0x72, 0x82, 0x8a, 0x3e, 0xbb, 0x16, 0x9c, 0xf5, 0xfb, 0x9a, 0x60, 0xd7, 0x40, 0x99, 0x47, + 0x9c, 0x40, 0x83, 0x01, 0x50, 0xa1, 0xfa, 0x9c, 0x09, 0x86, 0x37, 0xc6, 0x00, 0x75, 0x0a, 0xd8, + 0x2a, 0x38, 0x2c, 0xf0, 0x58, 0xa0, 0xb5, 0xed, 0x00, 0xb4, 0xc1, 0x61, 0x1b, 0x84, 0x7d, 0xa8, + 0x39, 0x8c, 0xd0, 0x98, 0xb4, 0xf5, 0x69, 0x97, 0x75, 0x99, 0x3c, 0x6a, 0xd1, 0x29, 0x89, 0x6e, + 0x4d, 0xee, 0xf2, 0x39, 0x63, 0x1d, 0xcd, 0xe9, 0xdb, 0xc4, 0x4b, 0x72, 0xa5, 0xb9, 0x1c, 0x87, + 0x9b, 0x90, 0x70, 0xf0, 0x26, 0x85, 0x94, 0xff, 0x4a, 0xa3, 0x9c, 0x1e, 0x15, 0x56, 0x8b, 0x68, + 0xfa, 0xc8, 0x27, 0x1c, 0x5c, 0xfc, 0x2d, 0x5a, 0x92, 0x32, 0x79, 0xa5, 0xa4, 0xec, 0xad, 0x1c, + 0x6d, 0xaa, 0x93, 0x72, 0xa5, 0x8e, 0x2a, 0xc1, 0xd5, 0xcc, 0xd3, 0x7d, 0x31, 0xc6, 0x99, 0xf1, + 0x17, 0x3e, 0x40, 0x88, 0x86, 0x9e, 0xc5, 0xa1, 0x6f, 0xdf, 0x06, 0xf9, 0x74, 0x49, 0xd9, 0x5b, + 0xac, 0xae, 0x3d, 0xdd, 0x17, 0x67, 0xa2, 0x66, 0x86, 0x86, 0x9e, 0x29, 0x8f, 0xb8, 0x82, 0x72, + 0x51, 0xc2, 0x61, 0x9e, 0x1f, 0x0a, 0xb0, 0x42, 0x4a, 0x44, 0x90, 0x5f, 0x90, 0xac, 0xcd, 0xa7, + 0xfb, 0xe2, 0xcb, 0xa4, 0xb9, 0x4e, 0x43, 0xaf, 0x16, 0x47, 0xae, 0xa2, 0x00, 0xa6, 0x28, 0x07, + 0x51, 0xd1, 0xb6, 0x20, 0x8c, 0x5a, 0x1c, 0xec, 0x80, 0xd1, 0xfc, 0x62, 0x49, 0xd9, 0x5b, 0x3b, + 0xda, 0x57, 0x5f, 0x31, 0x59, 0x9d, 0xf6, 0x29, 0x29, 0xa6, 0x64, 0xc4, 0xd7, 0xbd, 0x10, 0x32, + 0xb3, 0x30, 0x07, 0x2c, 0xff, 0xf9, 0xcc, 0xaf, 0x16, 0x08, 0xd1, 0xff, 0xa8, 0xfc, 0xfa, 0x0d, + 0xe5, 0x64, 0x49, 0xd6, 0xcc, 0x28, 0x24, 0x7e, 0x7d, 0x35, 0x5f, 0x75, 0x33, 0xfa, 0x34, 0xa7, + 0xb8, 0x59, 0xaf, 0x5e, 0x88, 0x98, 0x59, 0x7f, 0x0e, 0x5e, 0xfe, 0x23, 0x8d, 0x76, 0xa5, 0x57, + 0xb2, 0xfc, 0x0b, 0x42, 0x09, 0xed, 0x9e, 0x92, 0x4e, 0x87, 0x38, 0x61, 0x5f, 0xdc, 0x5e, 0xf9, + 0xae, 0x2d, 0xc0, 0xc5, 0x3b, 0x08, 0x05, 0xc0, 0x07, 0xc4, 0x01, 0x8b, 0xb8, 0xd2, 0xc0, 0x8c, + 0x99, 0x49, 0x22, 0x86, 0x8b, 0x4f, 0xd0, 0xb6, 0xcf, 0x61, 0x60, 0x09, 0x9b, 0x77, 0x41, 0x58, + 0x3d, 0x3b, 0xe8, 0x59, 0x3d, 0x18, 0x59, 0x40, 0x1d, 0xe6, 0x82, 0x2b, 0x4d, 0xcb, 0x98, 0xf9, + 0x08, 0x73, 0x29, 0x21, 0xe7, 0x76, 0xd0, 0x3b, 0x87, 0x91, 0x1e, 0xe7, 0xf1, 0x77, 0xe8, 0x0b, + 0x0a, 0xc3, 0xb7, 0xd2, 0x17, 0x24, 0xfd, 0x33, 0x0a, 0xc3, 0x57, 0xd9, 0x07, 0x68, 0x43, 0xde, + 0x3e, 0x7d, 0x0f, 0x0b, 0x3c, 0x5b, 0x1a, 0xb6, 0x18, 0x75, 0x0c, 0x83, 0xfa, 0xf8, 0x75, 0x74, + 0xcf, 0xc6, 0xdf, 0x20, 0x1c, 0x5d, 0x36, 0x87, 0x5e, 0x92, 0xe8, 0x75, 0x0a, 0xc3, 0x59, 0x70, + 0xf9, 0x5f, 0x05, 0x6d, 0x4b, 0x7b, 0x2a, 0xbe, 0xdf, 0x27, 0x8e, 0x9c, 0xb2, 0xc6, 0x00, 0x78, + 0xd2, 0xbb, 0x8b, 0xbf, 0x46, 0x59, 0x7b, 0x9a, 0xb2, 0x6c, 0xd7, 0xe5, 0x89, 0x3f, 0xeb, 0x33, + 0xf1, 0x8a, 0xeb, 0x72, 0x7c, 0x82, 0x56, 0x61, 0xe4, 0x83, 0x23, 0xc0, 0xb5, 0xda, 0x21, 0xa7, + 0xd2, 0x96, 0x95, 0xa3, 0xcf, 0xd5, 0x78, 0xa5, 0xa8, 0xd1, 0x4a, 0x51, 0x93, 0x95, 0xa2, 0xd6, + 0x18, 0xa1, 0xe6, 0x27, 0x63, 0x7c, 0x35, 0xe4, 0x14, 0x7f, 0x8f, 0xd6, 0xa0, 0xd3, 0x01, 0x47, + 0x90, 0x01, 0xc4, 0x02, 0x0b, 0xef, 0x13, 0x58, 0x9d, 0x10, 0x22, 0x85, 0xf2, 0xdf, 0x0a, 0xfa, + 0x72, 0xbe, 0x1b, 0x13, 0x88, 0xd7, 0x0e, 0x79, 0x90, 0x4c, 0xcf, 0x4d, 0x08, 0x81, 0xf8, 0x90, + 0xae, 0x9e, 0x8f, 0x46, 0x7a, 0x7e, 0x34, 0x64, 0x3a, 0x08, 0x22, 0x15, 0x32, 0x7e, 0xc9, 0x4c, + 0x12, 0x31, 0x5c, 0x7c, 0x88, 0x96, 0x6d, 0x8f, 0x85, 0xc9, 0x7c, 0xbf, 0xb3, 0x97, 0x04, 0xb8, + 0xff, 0x2b, 0xda, 0x7c, 0x75, 0x3f, 0xe0, 0x5d, 0xb4, 0xa3, 0xff, 0xdc, 0x34, 0xcc, 0xca, 0xa5, + 0xd1, 0xa8, 0x5b, 0xa6, 0x5e, 0x69, 0x35, 0xea, 0xd6, 0x55, 0xbd, 0xd5, 0xd4, 0x6b, 0xc6, 0x99, + 0xa1, 0x9f, 0x66, 0x53, 0x38, 0x87, 0x56, 0x9b, 0x66, 0xa3, 0x71, 0x66, 0x5d, 0x18, 0xad, 0x96, + 0x51, 0xff, 0x21, 0xab, 0x4c, 0x43, 0x46, 0xfd, 0xa7, 0xca, 0x8f, 0xc6, 0x69, 0x36, 0x5d, 0xbd, + 0xf8, 0xe7, 0xa1, 0xa0, 0xdc, 0x3d, 0x14, 0x94, 0xff, 0x1f, 0x0a, 0xca, 0xef, 0x8f, 0x85, 0xd4, + 0xdd, 0x63, 0x21, 0xf5, 0xdf, 0x63, 0x21, 0xf5, 0xcb, 0x71, 0x97, 0x88, 0x5e, 0xd8, 0x56, 0x1d, + 0xe6, 0x69, 0xd1, 0x0f, 0xf1, 0x80, 0x82, 0x18, 0x32, 0x7e, 0xad, 0x4d, 0x76, 0xf8, 0x68, 0xf6, + 0xdf, 0x44, 0xdc, 0xfa, 0x10, 0xb4, 0x97, 0xe5, 0x16, 0x3f, 0x7e, 0x13, 0x00, 0x00, 0xff, 0xff, + 0xe7, 0x04, 0xe0, 0xc6, 0x71, 0x06, 0x00, 0x00, } func (m *EventClaimExpired) Marshal() (dAtA []byte, err error) { @@ -602,6 +677,62 @@ func (m *EventApplicationOverserviced) MarshalToSizedBuffer(dAtA []byte) (int, e return len(dAtA) - i, nil } +func (m *EventApplicationReimbursementRequest) 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 *EventApplicationReimbursementRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventApplicationReimbursementRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Amount != nil { + { + size, err := m.Amount.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintEvent(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + if len(m.SessionId) > 0 { + i -= len(m.SessionId) + copy(dAtA[i:], m.SessionId) + i = encodeVarintEvent(dAtA, i, uint64(len(m.SessionId))) + i-- + dAtA[i] = 0x1a + } + if len(m.ServiceId) > 0 { + i -= len(m.ServiceId) + copy(dAtA[i:], m.ServiceId) + i = encodeVarintEvent(dAtA, i, uint64(len(m.ServiceId))) + i-- + dAtA[i] = 0x12 + } + if len(m.ApplicationAddr) > 0 { + i -= len(m.ApplicationAddr) + copy(dAtA[i:], m.ApplicationAddr) + i = encodeVarintEvent(dAtA, i, uint64(len(m.ApplicationAddr))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func encodeVarintEvent(dAtA []byte, offset int, v uint64) int { offset -= sovEvent(v) base := offset @@ -705,6 +836,31 @@ func (m *EventApplicationOverserviced) Size() (n int) { return n } +func (m *EventApplicationReimbursementRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ApplicationAddr) + if l > 0 { + n += 1 + l + sovEvent(uint64(l)) + } + l = len(m.ServiceId) + if l > 0 { + n += 1 + l + sovEvent(uint64(l)) + } + l = len(m.SessionId) + if l > 0 { + n += 1 + l + sovEvent(uint64(l)) + } + if m.Amount != nil { + l = m.Amount.Size() + n += 1 + l + sovEvent(uint64(l)) + } + return n +} + func sovEvent(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -1335,6 +1491,188 @@ func (m *EventApplicationOverserviced) Unmarshal(dAtA []byte) error { } return nil } +func (m *EventApplicationReimbursementRequest) 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 ErrIntOverflowEvent + } + 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: EventApplicationReimbursementRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventApplicationReimbursementRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ApplicationAddr", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + 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 ErrInvalidLengthEvent + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvent + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ApplicationAddr = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ServiceId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + 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 ErrInvalidLengthEvent + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvent + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ServiceId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SessionId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + 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 ErrInvalidLengthEvent + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvent + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SessionId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthEvent + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthEvent + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Amount == nil { + m.Amount = &types1.Coin{} + } + if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipEvent(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvent + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipEvent(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/tokenomics/types/tx.pb.go b/x/tokenomics/types/tx.pb.go index 91f06eeff..5bc7d33e4 100644 --- a/x/tokenomics/types/tx.pb.go +++ b/x/tokenomics/types/tx.pb.go @@ -133,7 +133,6 @@ type MsgUpdateParam struct { // specified in the `Params` message in `proof/params.proto.` Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` // Types that are valid to be assigned to AsType: - // // *MsgUpdateParam_AsString // *MsgUpdateParam_AsInt64 // *MsgUpdateParam_AsBytes From c3a235a737817a215b0c29b66b713a6b95e7c336 Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Tue, 20 Aug 2024 21:09:41 -0400 Subject: [PATCH 02/31] Checkpoint --- api/poktroll/application/params.pulsar.go | 3 + api/poktroll/tokenomics/event.pulsar.go | 4 +- .../protocol/architecture/_category_.json | 4 +- .../docs/protocol/architecture/network.md | 2 +- .../docs/protocol/tokenomics/_category_.json | 8 + .../docs/protocol/tokenomics/resources.md | 18 ++ .../tokenomics/token_logic_modules.md | 157 ++++++++++++++++++ .../docs/protocol/upgrades/_category_.json | 2 +- pkg/relayer/session/sessiontree.go | 7 +- proto/poktroll/shared/service.proto | 6 +- proto/poktroll/tokenomics/event.proto | 17 +- x/application/types/params.pb.go | 3 + x/session/keeper/session_hydrator.go | 1 + x/tokenomics/keeper/token_logic_modules.go | 84 +++++----- x/tokenomics/types/errors.go | 1 + x/tokenomics/types/event.pb.go | 4 +- 16 files changed, 268 insertions(+), 53 deletions(-) create mode 100644 docusaurus/docs/protocol/tokenomics/_category_.json create mode 100644 docusaurus/docs/protocol/tokenomics/resources.md create mode 100644 docusaurus/docs/protocol/tokenomics/token_logic_modules.md diff --git a/api/poktroll/application/params.pulsar.go b/api/poktroll/application/params.pulsar.go index d7854990e..f4918ce45 100644 --- a/api/poktroll/application/params.pulsar.go +++ b/api/poktroll/application/params.pulsar.go @@ -437,6 +437,9 @@ type Params struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // max_delegated_gateways defines the maximum number of gateways that a single + // application can delegate to. This is used to prevent performance issues + // in case the relay ring signature becomes too large. MaxDelegatedGateways uint64 `protobuf:"varint,1,opt,name=max_delegated_gateways,json=maxDelegatedGateways,proto3" json:"max_delegated_gateways,omitempty"` } diff --git a/api/poktroll/tokenomics/event.pulsar.go b/api/poktroll/tokenomics/event.pulsar.go index ae7a1d67b..c0303e634 100644 --- a/api/poktroll/tokenomics/event.pulsar.go +++ b/api/poktroll/tokenomics/event.pulsar.go @@ -3330,8 +3330,8 @@ func (x *EventApplicationOverserviced) GetEffectiveBurn() *v1beta1.Coin { return nil } -// EventApplicationReimbursementRequest is emitted when an application requests a -// reimbursement +// EventApplicationReimbursementRequest is emitted when an application requests +// a reimbursement type EventApplicationReimbursementRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache diff --git a/docusaurus/docs/protocol/architecture/_category_.json b/docusaurus/docs/protocol/architecture/_category_.json index c4be422a5..985d17b7b 100644 --- a/docusaurus/docs/protocol/architecture/_category_.json +++ b/docusaurus/docs/protocol/architecture/_category_.json @@ -1,6 +1,6 @@ { - "label": "Architecture", - "position": 7, + "label": "[Outdated] Architecture", + "position": 6, "link": { "type": "generated-index", "description": "Documentation related to the high-level design, flows and components of the poktroll repo." diff --git a/docusaurus/docs/protocol/architecture/network.md b/docusaurus/docs/protocol/architecture/network.md index d0e25f1d3..b7949986e 100644 --- a/docusaurus/docs/protocol/architecture/network.md +++ b/docusaurus/docs/protocol/architecture/network.md @@ -1,5 +1,5 @@ --- -title: Pocket Actors, Nodes & Data Availability Network +title: Outdated - Pocket Actors, Nodes & Data Availability Network sidebar_position: 1 --- diff --git a/docusaurus/docs/protocol/tokenomics/_category_.json b/docusaurus/docs/protocol/tokenomics/_category_.json new file mode 100644 index 000000000..c23caaa17 --- /dev/null +++ b/docusaurus/docs/protocol/tokenomics/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "Tokenomics", + "position": 5, + "link": { + "type": "generated-index", + "description": "Documentation related to Pocket Network tokenomics." + } +} diff --git a/docusaurus/docs/protocol/tokenomics/resources.md b/docusaurus/docs/protocol/tokenomics/resources.md new file mode 100644 index 000000000..9b31e6ec1 --- /dev/null +++ b/docusaurus/docs/protocol/tokenomics/resources.md @@ -0,0 +1,18 @@ +--- +title: Tokenomics Resources +sidebar_position: 1 +--- + +# Tokenomics Resources + +The following resources serve as the foundation for the Shannon Upgrade Tokenomics. + +It is an active an ever evolving work, but the following resources are the best +starting references: + +- [Token Logic Module](https://docs.pokt.network/pokt-protocol/the-shannon-upgrade/proposed-tokenomics/token-logic-modules) design approach. +- [Shannon Tokenomics Static](https://github.com/pokt-network/shannon-tokenomics-static-tests) modeling & evaluation +- [Relay Mining](https://arxiv.org/abs/2305.10672) paper +- [Probabilistic Proofs](https://github.com/pokt-network/pocket-core/blob/staging/docs/proposals/probabilistic_proofs.md) design + +Thank you to [@Rama_stdout](https://x.com/Rama_stdout), [@shane8burger](https://x.com/shane8burger) and [@olshansky](https://x.com/olshansky) for the contributions! diff --git a/docusaurus/docs/protocol/tokenomics/token_logic_modules.md b/docusaurus/docs/protocol/tokenomics/token_logic_modules.md new file mode 100644 index 000000000..3fd36ddd0 --- /dev/null +++ b/docusaurus/docs/protocol/tokenomics/token_logic_modules.md @@ -0,0 +1,157 @@ +--- +title: Token Logic Modules +sidebar_position: 2 +--- + +# Token Logic Modules + +- [Introduction](#introduction) +- [Background: Relay Mining Payable Relay Accumulation](#background-relay-mining-payable-relay-accumulation) +- [TLM Pre-processor: Claim Settlement Limit](#tlm-pre-processor-claim-settlement-limit) +- [TLM: Mint=Burn (MEB)](#tlm-mintburn-meb) +- [TLM: Global Mint (GM)](#tlm-global-mint-gm) +- [TLM: Global Mint Reimbursement Request (GMRR)](#tlm-global-mint-reimbursement-request-gmrr) + +## Introduction + +:::warning + +Note that this is an active WIP and the [resources here](./resources.md) are the best starting references to learn more. + +::: + +Token Logic Modules (TLMs) processing involves: + +1. `TLM pre-processing` - A general pre-processor determining the amount of coins to settle per claim +2. `TLM processing` - Individual processing each TLM independent of the other + +## Background: Relay Mining Payable Relay Accumulation + +Per **Algorithm 1** of the [Relay Mining paper](https://arxiv.org/pdf/2305.10672), +the maximum amount a supplier can claim from an application in a single session is +proportional to the Application's stake divided by the number of nodes in the session +as see in the following image: + +![Algorithm 1](https://github.com/user-attachments/assets/d1a61535-aa31-447d-88ea-c8d14dcb20c6) + +## TLM Pre-processor: Claim Settlement Limit + +**Prior to** processing each individual TLM, we need to understand if the amount claimed +by the supplier adheres to the maximum allowed per the limits set by Relay Mining. + +Suppliers always have the option to over-service an application (**i.e. do free work**), +in exchange for providing a good service to the network, but their on-chain rewards +are still limited as a function of the application's stake before the session started +and the number of nodes in the session. + +:::note + +TODO_POST_MAINNET: After the Shannon upgrade, the team at Grove has a lot of ideas +related to [supplier gossipin](https://www.notion.so/buildwithgrove/Off-chain-Application-Stake-Tracking-6a8bebb107db4f7f9dc62cbe7ba555f7?pvs=4) but that +is out of scope for the initial implementation. + +::: + +```mermaid +--- +title: "Token Logic Modules Processor" +--- +flowchart TB + CSA(["Claim Settlement Amount (CSA)"]) + MCS(["MaxClaimPerSupplier (MCS)
= (AppStake / NumNodesPerSession)"]) + CC{"Is CSA > MCS?"} + Update(Set SA = MCS
Broadcast Event) + SOAE{{Application Overserviced
Event}} + TLMP[["TLM Processor (SA)"]] + + CSA -- CSA --> CC + MCS -- MCS --> CC + + Update -..-> SOAE + CC -- Yes --> Update + CC -- No
SA=CSA --> TLMP + Update -- SA=CSA --> TLMP + + TLMP --SA--> TLMBEM[[TLM: Burn Equals Mint]] + TLMP --SA--> TLMGI[[TLM: Global Inflation]] + TLMP --SA--> TLMGIRR[[TLM: Global Inflation Reimbursment Request]] + + classDef tlm fill:#54ebd5,stroke:#333,stroke-width:2px; + classDef question fill:#e3db6d,stroke:#333,stroke-width:2px; + classDef event fill:#e8b761,stroke:#333,stroke-width:2px; + + class TLMP,TLMBEM,TLMGI,TLMGIRR tlm; + class SOAE event; + class CC question; +``` + +## TLM: Mint=Burn (MEB) + +The `Mint=Burn` TLM is, _theoretically_, the only TLM necessary when the network +reaches equilibrium in the far future. + +Put simply, it is a transfer of tokens from the application to the supplier based on the +amount of work done by the supplier. + +The same amount of tokens that is minted in the supplier module is burned from the application module. +The stake of the application paying for work is reduced and the rewards are distributed to the supplier +and its revenue shareholder addresses. + +```mermaid +--- +title: "Token Logic Module: Mint=Burn" +--- +flowchart TD + SA(["Settlement Amount (SA)"]) + + SA -- Mint SA coins --> SM + SA -- Burn SA coins--> AM + + subgraph SO[Supplier Operations] + SM[[Supplier Module]] + SK[(Supplier Keeper)] + SD{Distribute SA coins} + OPA[Operator Address] + OA[Owner Address] + RSA[Revenue Share Addresses] + + SM -.- SK + SD -->|% Distribution
Increase Balance| OPA + SD -->|% Distribution
Increase Balance| OA + SD -->|% Distribution
Increase Balance| RSA + end + + subgraph AO[Application Operations] + AM[[Application Module]] + AK[(Application Keeper)] + AA[Application Address] + + AM -.- AK + AK -. Reduce Stake by CSA .-> AA + end + + SM --> SD + + + classDef module fill:#f9f,stroke:#333,stroke-width:2px; + classDef address fill:#bbf,stroke:#333,stroke-width:2px; + classDef question fill:#e3db6d,stroke:#333,stroke-width:2px; + classDef event fill:#e8b761,stroke:#333,stroke-width:2px; + + class SM,AM module; + class RSA,OA,OPA,AA address; +``` + +## TLM: Global Mint (GM) + +TLMGlobalMint is the token logic module that mints new tokens based on the +on global governance parameters in order to reward the participants providing +services while keeping inflation in check. + +## TLM: Global Mint Reimbursement Request (GMRR) + +TLMGlobalMintReimbursementRequest is the token logic module that complements +TLMGlobalMint to enable permissionless demand. In order to prevent self-dealing +attacks, applications will be overcharged by the amount equal to global inflation, +those funds will be sent to the DAO/PNF, and event will be emitted to be used +for reimbursements. diff --git a/docusaurus/docs/protocol/upgrades/_category_.json b/docusaurus/docs/protocol/upgrades/_category_.json index 5fe4a715b..2e80f4c80 100644 --- a/docusaurus/docs/protocol/upgrades/_category_.json +++ b/docusaurus/docs/protocol/upgrades/_category_.json @@ -1,6 +1,6 @@ { "label": "Upgrades", - "position": 7, + "position": 4, "link": { "type": "generated-index", "description": "Documentation related to Pocket Network protocol upgrades." diff --git a/pkg/relayer/session/sessiontree.go b/pkg/relayer/session/sessiontree.go index 843186b0d..d54992c82 100644 --- a/pkg/relayer/session/sessiontree.go +++ b/pkg/relayer/session/sessiontree.go @@ -19,7 +19,11 @@ import ( var _ relayer.SessionTree = (*sessionTree)(nil) // sessionTree is an implementation of the SessionTree interface. -// TODO_TEST: Add tests to the sessionTree. +// TODO_BETA(@red-0ne): Per the Relay Mining paper, we need to optimistically store +// the number of requests that an application can pay for. This needs to be tracked +// based on the app's stake in the beginning of a session and the number of nodes +// per session. An operator should be able to specify "overservicing_okay" whereby +// it keeps replying to requests even though it may not get paid for them. type sessionTree struct { // sessionMu is a mutex used to protect sessionTree operations from concurrent access. sessionMu *sync.Mutex @@ -65,6 +69,7 @@ type sessionTree struct { // NewSessionTree creates a new sessionTree from a Session and a storePrefix. It also takes a function // removeFromRelayerSessions that removes the sessionTree from the RelayerSessionsManager. // It returns an error if the KVStore fails to be created. +// TODO_BETA(@red-0ne): When starting a new session, check how many relays the app can handle. func NewSessionTree( sessionHeader *sessiontypes.SessionHeader, supplierOperatorAddress *cosmostypes.AccAddress, diff --git a/proto/poktroll/shared/service.proto b/proto/poktroll/shared/service.proto index 4777b0ccb..f6aa00d78 100644 --- a/proto/poktroll/shared/service.proto +++ b/proto/poktroll/shared/service.proto @@ -13,7 +13,7 @@ message Service { // For example, what if we want to request a session for a certain service but with some additional configs that identify it? string id = 1; // Unique identifier for the service - // TODO_MAINNET: Remove this. + // TODO_BETA: Either remove this or rename it to alias. string name = 2; // (Optional) Semantic human readable name for the service // The cost of a single relay for this service in terms of compute units. @@ -30,7 +30,7 @@ message Service { // ApplicationServiceConfig holds the service configuration the application stakes for message ApplicationServiceConfig { - // TODO_MAINNET: Avoid embedding the full Service because we just need the ID. + // TODO_BETA: Avoid embedding the full Service because we just need the ID. Service service = 1; // The Service for which the application is configured // TODO_MAINNET: There is an opportunity for applications to advertise the max @@ -40,7 +40,7 @@ message ApplicationServiceConfig { // SupplierServiceConfig holds the service configuration the supplier stakes for message SupplierServiceConfig { - // TODO_MAINNET: Avoid embedding the full Service because we just need the ID. + // TODO_BETA: Avoid embedding the full Service because we just need the ID. Service service = 1; // The Service for which the supplier is configured repeated SupplierEndpoint endpoints = 2; // List of endpoints for the service repeated ServiceRevenueShare rev_share = 3; // List of revenue share configurations for the service diff --git a/proto/poktroll/tokenomics/event.proto b/proto/poktroll/tokenomics/event.proto index 76ef86e5c..00a089f8f 100644 --- a/proto/poktroll/tokenomics/event.proto +++ b/proto/poktroll/tokenomics/event.proto @@ -44,16 +44,25 @@ message EventRelayMiningDifficultyUpdated { uint64 new_num_relays_ema = 5; } -// EventApplicationOverserviced is emitted when an application has less stake -// than the expected burn. +// EventApplicationOverserviced is emitted when an application has less stake than +// what a supplier is claiming (i.e. burn is not high enough). message EventApplicationOverserviced { string application_addr = 1; + string supplier_addr = 2; + cosmos.base.v1beta1.Coin expected_burn = 3; + cosmos.base.v1beta1.Coin effective_burn = 4; +} + +// EventSupplierExceededClaimableAmount is emitted when a supplier application has less stake +// than the expected burn. +message EventSupplierExceededClaimableAmount { + string supplier_addr = 1; cosmos.base.v1beta1.Coin expected_burn = 2; cosmos.base.v1beta1.Coin effective_burn = 3; } -// EventApplicationReimbursementRequest is emitted when an application requests a -// reimbursement +// EventApplicationReimbursementRequest is emitted when an application requests +// a reimbursement message EventApplicationReimbursementRequest { string application_addr = 1; string service_id = 2; diff --git a/x/application/types/params.pb.go b/x/application/types/params.pb.go index a2caf90b1..227e0f149 100644 --- a/x/application/types/params.pb.go +++ b/x/application/types/params.pb.go @@ -26,6 +26,9 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // Params defines the parameters for the module. type Params struct { + // max_delegated_gateways defines the maximum number of gateways that a single + // application can delegate to. This is used to prevent performance issues + // in case the relay ring signature becomes too large. MaxDelegatedGateways uint64 `protobuf:"varint,1,opt,name=max_delegated_gateways,json=maxDelegatedGateways,proto3" json:"max_delegated_gateways" yaml:"max_delegated_gateways"` } diff --git a/x/session/keeper/session_hydrator.go b/x/session/keeper/session_hydrator.go index e0711dd3a..60c292836 100644 --- a/x/session/keeper/session_hydrator.go +++ b/x/session/keeper/session_hydrator.go @@ -59,6 +59,7 @@ func NewSessionHydrator( // GetSession implements of the exposed `UtilityModule.GetSession` function // TECHDEBT(#519,#348): Add custom error types depending on the type of issue that occurred and assert on them in the unit tests. +// TODO_BETA: Consider returning an error if the application's stake has become very low. func (k Keeper) HydrateSession(ctx context.Context, sh *sessionHydrator) (*types.Session, error) { logger := k.Logger().With("method", "hydrateSession") diff --git a/x/tokenomics/keeper/token_logic_modules.go b/x/tokenomics/keeper/token_logic_modules.go index 0190d78b3..99cff2611 100644 --- a/x/tokenomics/keeper/token_logic_modules.go +++ b/x/tokenomics/keeper/token_logic_modules.go @@ -98,6 +98,7 @@ type TokenLogicModuleProcessor func( var tokenLogicModuleProcessorMap = map[TokenLogicModule]TokenLogicModuleProcessor{ TLMRelayBurnEqualsMint: Keeper.TokenLogicModuleRelayBurnEqualsMint, TLMGlobalMint: Keeper.TokenLogicModuleGlobalMint, + // TLMGlobalMintReimbursementRequest: Keeper.TokenLogicModuleGlobalMintReimbursementRequest, } func init() { @@ -107,9 +108,9 @@ func init() { } } -// ProcessTokenLogicModules is responsible for calling all of the token logic -// modules (i.e. post session claim accounting) necessary to burn, mint or transfer -// tokens as a result of the amount of work (i.e. compute units) done. +// ProcessTokenLogicModules is the main TLM processor. It is responsible for calling +// all of the token logic module necessary to limit, burn, mint or transfer tokens +// as a result of the amount of work (i.e. compute units) done and governance parameters. func (k Keeper) ProcessTokenLogicModules( ctx context.Context, claim *prooftypes.Claim, // IMPORTANT: It is assumed the proof for the claim has been validated BEFORE calling this function @@ -117,17 +118,17 @@ func (k Keeper) ProcessTokenLogicModules( logger := k.Logger().With("method", "ProcessTokenLogicModules") // Declaring variables that will be emitted by telemetry - settlementCoin := cosmostypes.NewCoin("upokt", math.NewInt(0)) + claimSettlementCoin := cosmostypes.NewCoin("upokt", math.NewInt(0)) isSuccessful := false // This is emitted only when the function returns (successful or not) defer telemetry.EventSuccessCounter( "process_token_logic_modules", func() float32 { - if settlementCoin.Amount.BigInt() == nil { + if claimSettlementCoin.Amount.BigInt() == nil { return 0 } - return float32(settlementCoin.Amount.Int64()) + return float32(claimSettlementCoin.Amount.Int64()) }, func() bool { return isSuccessful }, ) @@ -196,6 +197,7 @@ func (k Keeper) ProcessTokenLogicModules( if err != nil { return tokenomicstypes.ErrTokenomicsRootHashInvalid.Wrapf("%v", err) } + // TODO_POST_MAINNET: Because of how things have evolved, we are now using // root.Count (numRelays) instead of root.Sum (numComputeUnits) to determine // the amount of work done. This is because the compute_units_per_relay is @@ -207,7 +209,7 @@ func (k Keeper) ProcessTokenLogicModules( // Determine the total number of tokens that'll be used for settling the session. // When the network achieves equilibrium, this will be the mint & burn. - settlementCoin, err = k.numRelaysToCoin(ctx, numRelays, &service) + claimSettlementCoin, err = k.numRelaysToCoin(ctx, numRelays, &service) if err != nil { return err } @@ -230,18 +232,33 @@ func (k Keeper) ProcessTokenLogicModules( // Helpers for logging the same metadata throughout this function calls logger = logger.With( "num_relays", numRelays, - "num_settlement_upokt", settlementCoin.Amount, + "claim_settlement_upokt", claimSettlementCoin.Amount, "session_id", sessionHeader.GetSessionId(), "service_id", sessionHeader.GetService().Id, "supplier_operator", supplier.OperatorAddress, "application", application.Address, ) - logger.Info(fmt.Sprintf("About to start processing TLMs for (%d) relays equaling to (%s) coins", numRelays, settlementCoin)) + logger.Info(fmt.Sprintf("About to start processing TLMs for (%d) relays equaling to (%s) upokt claimed", numRelays, claimSettlementCoin)) + + maxClaimableAmount := application.GetStake().QuoUint64(uint64(relayMiningDifficulty.NumNodesPerSession)) + + // Reduce the settlement amount if the application was over-serviced + var actualSettlementCoin cosmostypes.Coin + if application.GetStake().IsLT(claimSettlementCoin) { + actualSettlementCoin, err = k.handleOverservicedApplication(ctx, &application, claimSettlementCoin) + if err != nil { + return err + } + logger.Warn(fmt.Sprintf("Application with address %s was over-serviced so the actual amount being settled is (%v) instead of the claimed amount (%v) ", application.Address, actualSettlementCoin, claimSettlementCoin)) + } else { + actualSettlementCoin = claimSettlementCoin + } + logger = logger.With("actual_settlement_upokt", actualSettlementCoin) // Execute all the token logic modules processors for tlm, tlmProcessor := range tokenLogicModuleProcessorMap { logger.Info(fmt.Sprintf("Starting to execute TLM %q", tlm)) - if err := tlmProcessor(k, ctx, &service, &application, &supplier, settlementCoin, &relayMiningDifficulty); err != nil { + if err := tlmProcessor(k, ctx, &service, claim.SessionHeader, &application, &supplier, actualSettlementCoin, &relayMiningDifficulty); err != nil { return err } logger.Info(fmt.Sprintf("Finished executing TLM %q", tlm)) @@ -277,7 +294,7 @@ func (k Keeper) TokenLogicModuleRelayBurnEqualsMint( return err } - // NB: We are doing a mint & burn + transfer, instead of a simple transfer + // DEV_NOTE: We are doing a mint & burn + transfer, instead of a simple transfer // of funds from the supplier to the application in order to enable second // order economic effects with more optionality. This could include funds // going to pnf, delegators, enabling bonuses/rebates, etc... @@ -305,19 +322,6 @@ func (k Keeper) TokenLogicModuleRelayBurnEqualsMint( } logger.Info(fmt.Sprintf("sent (%v) from the supplier module to the supplier account with address %q", settlementCoin, supplier.OperatorAddress)) - // TODO_MAINNET: Decide on the behaviour here when an app is over serviced. - // If an app has 10 POKT staked, but the supplier earned 20 POKT. We still - // end up minting 20 POKT but only burn 10 POKT from the app. There are - // questions and nuance here that needs to be addressed. - - // Verify that the application has enough uPOKT to pay for the services it consumed - if application.GetStake().IsLT(settlementCoin) { - settlementCoin, err = k.handleOverservicedApplication(ctx, application, settlementCoin) - if err != nil { - return err - } - } - // Burn uPOKT from the application module account which was held in escrow // on behalf of the application account. if err = k.bankKeeper.BurnCoins( @@ -404,8 +408,8 @@ func (k Keeper) TokenLogicModuleGlobalMint( // Check and log the total amount of coins distributed totalDistributedCoins := appCoin.Add(supplierCoin).Add(*daoCoin).Add(*serviceCoin).Add(*proposerCoin) - if totalDistributedCoins.Amount.BigInt().Cmp(settlementCoin.Amount.BigInt()) != 0 { - logger.Error(fmt.Sprintf("TODO_MAINNET: Verify why the total distributed coins (%v) do not equal the settlement coins (%v). Likely floating point arithmetic.", totalDistributedCoins, settlementCoin.Amount.BigInt())) + if totalDistributedCoins.Amount.BigInt().Cmp(newMintCoins[0].Amount.BigInt()) != 0 { + return tokenomictypes.ErrTokenomicsAmountMismatch.Wrapf("the total distributed coins (%v) do not equal the settlement coins (%v). Likely floating point arithmetic.", totalDistributedCoins, settlementCoin.Amount.BigInt()) } logger.Info(fmt.Sprintf("distributed (%v) coins to the application, supplier, DAO, source owner, and proposer", totalDistributedCoins)) @@ -435,15 +439,13 @@ func (k Keeper) TokenLogicModuleGlobalMintReimbursementRequest( settlementCoins cosmostypes.Coin, relayMiningDifficulty *tokenomictypes.RelayMiningDifficulty, ) error { - logger := k.Logger().With("method", "TokenLogicModuleGlobalMint") + // logger := k.Logger().With("method", "TokenLogicModuleGlobalMintReimbursementRequest") // Determine how much new uPOKT to mint based on global inflation newMintCoins, _ := calculateGlobalMintAllocationFromSettlementAmount(settlementCoins) - - // EventApplicationReimbursementRequest - reimbursementRequest := tokenomictypes.EventApplicationReimbursementRequest{ + reimbursementRequestEvent := tokenomictypes.EventApplicationReimbursementRequest{ ApplicationAddr: application.Address, ServiceId: service.Id, SessionId: sessionHeader.SessionId, @@ -451,7 +453,7 @@ func (k Keeper) TokenLogicModuleGlobalMintReimbursementRequest( } eventManager := cosmostypes.UnwrapSDKContext(ctx).EventManager() - if err := eventManager.EmitTypedEvent(&reimbursementRequest); err != nil { + if err := eventManager.EmitTypedEvent(&reimbursementRequestEvent); err != nil { return tokenomicstypes.ErrTokenomicsApplicationReimbursementRequestFailed.Wrapf( "application address: %s; service Id %s; session Id: %s; amount: %s", application.GetAddress(), @@ -496,20 +498,25 @@ func (k Keeper) sendRewardsToAccount( return &coinToAcc, nil } +// handleOverservicedApplication handles the case where an application has been over-serviced. +// Per Algorithm #1 in the Relay Mining paper, the maximum amount that a single supplier +// can claim in a session is AppStake/NumNodesPerSession. +// If this is not the case, then the supplier essentially did "free work" and the actual +// claim amount is less than what was claimed. +// Ref: https://arxiv.org/pdf/2305.10672 func (k Keeper) handleOverservicedApplication( ctx context.Context, application *apptypes.Application, - settlementCoins cosmostypes.Coin, + claimSettlementCoin cosmostypes.Coin, ) ( - newSettlementCoins cosmostypes.Coin, + actualSettlementCoins cosmostypes.Coin, err error, ) { logger := k.Logger().With("method", "handleOverservicedApplication") - // over-serviced application logger.Warn(fmt.Sprintf( "THIS SHOULD NEVER HAPPEN. Application with address %s needs to be charged more than it has staked: %v > %v", application.Address, - settlementCoins, + claimSettlementCoin, application.Stake, )) @@ -518,7 +525,7 @@ func (k Keeper) handleOverservicedApplication( // probabilistic proofs and add all the parameter logic. Do we touch the application balance? // Do we just let it go into debt? Do we penalize the application? Do we unstake it? Etc... // See this document from @red-0ne and @bryanchriswhite for more context: notion.so/buildwithgrove/Off-chain-Application-Stake-Tracking-6a8bebb107db4f7f9dc62cbe7ba555f7 - expectedBurn := settlementCoins + expectedBurn := claimSettlementCoin applicationOverservicedEvent := &tokenomicstypes.EventApplicationOverserviced{ ApplicationAddr: application.Address, @@ -535,6 +542,9 @@ func (k Keeper) handleOverservicedApplication( application.GetStake().String(), ) } + + // TODO(@red-0ne) + return *application.Stake, nil } @@ -592,7 +602,7 @@ func (k Keeper) distributeSupplierRewardsToShareHolders( shareAmountMap := GetShareAmountMap(serviceRevShare, amountToDistribute) for shareHolderAddress, shareAmount := range shareAmountMap { - // TODO_IN_THIS_PR: Why don't we use sendRewardsToAccount here? + // TODO_TECHDEBT(@red-0ne): Refactor to reuse the sendRewardsToAccount helper here. shareAmountCoin := cosmostypes.NewCoin(volatile.DenomuPOKT, math.NewInt(int64(shareAmount))) shareAmountCoins := cosmostypes.NewCoins(shareAmountCoin) shareHolderAccAddress, err := sdk.AccAddressFromBech32(shareHolderAddress) diff --git a/x/tokenomics/types/errors.go b/x/tokenomics/types/errors.go index 6e7c23a0d..91b2d761e 100644 --- a/x/tokenomics/types/errors.go +++ b/x/tokenomics/types/errors.go @@ -33,4 +33,5 @@ var ( ErrTokenomicsSupplierOwnerAddressInvalid = sdkerrors.Register(ModuleName, 1124, "the supplier owner address in the claim is not a valid bech32 address") ErrTokenomicsSupplierRevShareFailed = sdkerrors.Register(ModuleName, 1125, "failed to send rev share to supplier shareholders") ErrTokenomicsApplicationReimbursementRequestFailed = sdkerrors.Register(ModuleName, 1126, "failed to send application reimbursement request event") + ErrTokenomicsAmountMismatch = sdkerrors.Register(ModuleName, 1127, "an unexpected amount mismatch occurred") ) diff --git a/x/tokenomics/types/event.pb.go b/x/tokenomics/types/event.pb.go index 945d4ab97..1585b4fcf 100644 --- a/x/tokenomics/types/event.pb.go +++ b/x/tokenomics/types/event.pb.go @@ -335,8 +335,8 @@ func (m *EventApplicationOverserviced) GetEffectiveBurn() *types1.Coin { return nil } -// EventApplicationReimbursementRequest is emitted when an application requests a -// reimbursement +// EventApplicationReimbursementRequest is emitted when an application requests +// a reimbursement type EventApplicationReimbursementRequest struct { ApplicationAddr string `protobuf:"bytes,1,opt,name=application_addr,json=applicationAddr,proto3" json:"application_addr,omitempty"` ServiceId string `protobuf:"bytes,2,opt,name=service_id,json=serviceId,proto3" json:"service_id,omitempty"` From 846bc1d08f13d4b3903edbcb502ec9fcb03bc262 Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Wed, 21 Aug 2024 14:55:06 -0400 Subject: [PATCH 03/31] Finished first version of the documentation --- api/poktroll/shared/service.pulsar.go | 6 +- api/poktroll/tokenomics/event.pulsar.go | 176 +++++++--- .../docs/protocol/tokenomics/resources.md | 9 +- .../tokenomics/token_logic_modules.md | 200 ++++++++++-- proto/poktroll/tokenomics/event.proto | 15 +- x/session/keeper/session_hydrator.go | 2 +- x/session/keeper/session_hydrator_test.go | 2 +- x/shared/types/service.pb.go | 6 +- x/tokenomics/keeper/token_logic_modules.go | 301 +++++++++--------- .../keeper/token_logic_modules_test.go | 3 + .../keeper/update_relay_mining_difficulty.go | 35 +- x/tokenomics/types/errors.go | 2 +- x/tokenomics/types/event.pb.go | 173 ++++++---- 13 files changed, 601 insertions(+), 329 deletions(-) diff --git a/api/poktroll/shared/service.pulsar.go b/api/poktroll/shared/service.pulsar.go index 9ca7b82a1..973ed5071 100644 --- a/api/poktroll/shared/service.pulsar.go +++ b/api/poktroll/shared/service.pulsar.go @@ -3420,7 +3420,7 @@ type Service struct { // For example, what if we want to request a session for a certain service but with some additional configs that identify it? Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` // Unique identifier for the service - // TODO_MAINNET: Remove this. + // TODO_BETA: Either remove this or rename it to alias. Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` // (Optional) Semantic human readable name for the service // The cost of a single relay for this service in terms of compute units. // Must be used alongside the global 'compute_units_to_tokens_multipler' to calculate the cost of a relay for this service. @@ -3487,7 +3487,7 @@ type ApplicationServiceConfig struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // TODO_MAINNET: Avoid embedding the full Service because we just need the ID. + // TODO_BETA: Avoid embedding the full Service because we just need the ID. Service *Service `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"` // The Service for which the application is configured } @@ -3524,7 +3524,7 @@ type SupplierServiceConfig struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // TODO_MAINNET: Avoid embedding the full Service because we just need the ID. + // TODO_BETA: Avoid embedding the full Service because we just need the ID. Service *Service `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"` // The Service for which the supplier is configured Endpoints []*SupplierEndpoint `protobuf:"bytes,2,rep,name=endpoints,proto3" json:"endpoints,omitempty"` // List of endpoints for the service RevShare []*ServiceRevenueShare `protobuf:"bytes,3,rep,name=rev_share,json=revShare,proto3" json:"rev_share,omitempty"` // List of revenue share configurations for the service diff --git a/api/poktroll/tokenomics/event.pulsar.go b/api/poktroll/tokenomics/event.pulsar.go index c0303e634..52ef98cfa 100644 --- a/api/poktroll/tokenomics/event.pulsar.go +++ b/api/poktroll/tokenomics/event.pulsar.go @@ -1820,6 +1820,7 @@ func (x *fastReflection_EventRelayMiningDifficultyUpdated) ProtoMethods() *proto var ( md_EventApplicationOverserviced protoreflect.MessageDescriptor fd_EventApplicationOverserviced_application_addr protoreflect.FieldDescriptor + fd_EventApplicationOverserviced_supplier_addr protoreflect.FieldDescriptor fd_EventApplicationOverserviced_expected_burn protoreflect.FieldDescriptor fd_EventApplicationOverserviced_effective_burn protoreflect.FieldDescriptor ) @@ -1828,6 +1829,7 @@ func init() { file_poktroll_tokenomics_event_proto_init() md_EventApplicationOverserviced = File_poktroll_tokenomics_event_proto.Messages().ByName("EventApplicationOverserviced") fd_EventApplicationOverserviced_application_addr = md_EventApplicationOverserviced.Fields().ByName("application_addr") + fd_EventApplicationOverserviced_supplier_addr = md_EventApplicationOverserviced.Fields().ByName("supplier_addr") fd_EventApplicationOverserviced_expected_burn = md_EventApplicationOverserviced.Fields().ByName("expected_burn") fd_EventApplicationOverserviced_effective_burn = md_EventApplicationOverserviced.Fields().ByName("effective_burn") } @@ -1903,6 +1905,12 @@ func (x *fastReflection_EventApplicationOverserviced) Range(f func(protoreflect. return } } + if x.SupplierAddr != "" { + value := protoreflect.ValueOfString(x.SupplierAddr) + if !f(fd_EventApplicationOverserviced_supplier_addr, value) { + return + } + } if x.ExpectedBurn != nil { value := protoreflect.ValueOfMessage(x.ExpectedBurn.ProtoReflect()) if !f(fd_EventApplicationOverserviced_expected_burn, value) { @@ -1932,6 +1940,8 @@ func (x *fastReflection_EventApplicationOverserviced) Has(fd protoreflect.FieldD switch fd.FullName() { case "poktroll.tokenomics.EventApplicationOverserviced.application_addr": return x.ApplicationAddr != "" + case "poktroll.tokenomics.EventApplicationOverserviced.supplier_addr": + return x.SupplierAddr != "" case "poktroll.tokenomics.EventApplicationOverserviced.expected_burn": return x.ExpectedBurn != nil case "poktroll.tokenomics.EventApplicationOverserviced.effective_burn": @@ -1954,6 +1964,8 @@ func (x *fastReflection_EventApplicationOverserviced) Clear(fd protoreflect.Fiel switch fd.FullName() { case "poktroll.tokenomics.EventApplicationOverserviced.application_addr": x.ApplicationAddr = "" + case "poktroll.tokenomics.EventApplicationOverserviced.supplier_addr": + x.SupplierAddr = "" case "poktroll.tokenomics.EventApplicationOverserviced.expected_burn": x.ExpectedBurn = nil case "poktroll.tokenomics.EventApplicationOverserviced.effective_burn": @@ -1977,6 +1989,9 @@ func (x *fastReflection_EventApplicationOverserviced) Get(descriptor protoreflec case "poktroll.tokenomics.EventApplicationOverserviced.application_addr": value := x.ApplicationAddr return protoreflect.ValueOfString(value) + case "poktroll.tokenomics.EventApplicationOverserviced.supplier_addr": + value := x.SupplierAddr + return protoreflect.ValueOfString(value) case "poktroll.tokenomics.EventApplicationOverserviced.expected_burn": value := x.ExpectedBurn return protoreflect.ValueOfMessage(value.ProtoReflect()) @@ -2005,6 +2020,8 @@ func (x *fastReflection_EventApplicationOverserviced) Set(fd protoreflect.FieldD switch fd.FullName() { case "poktroll.tokenomics.EventApplicationOverserviced.application_addr": x.ApplicationAddr = value.Interface().(string) + case "poktroll.tokenomics.EventApplicationOverserviced.supplier_addr": + x.SupplierAddr = value.Interface().(string) case "poktroll.tokenomics.EventApplicationOverserviced.expected_burn": x.ExpectedBurn = value.Message().Interface().(*v1beta1.Coin) case "poktroll.tokenomics.EventApplicationOverserviced.effective_burn": @@ -2041,6 +2058,8 @@ func (x *fastReflection_EventApplicationOverserviced) Mutable(fd protoreflect.Fi return protoreflect.ValueOfMessage(x.EffectiveBurn.ProtoReflect()) case "poktroll.tokenomics.EventApplicationOverserviced.application_addr": panic(fmt.Errorf("field application_addr of message poktroll.tokenomics.EventApplicationOverserviced is not mutable")) + case "poktroll.tokenomics.EventApplicationOverserviced.supplier_addr": + panic(fmt.Errorf("field supplier_addr of message poktroll.tokenomics.EventApplicationOverserviced is not mutable")) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.tokenomics.EventApplicationOverserviced")) @@ -2056,6 +2075,8 @@ func (x *fastReflection_EventApplicationOverserviced) NewField(fd protoreflect.F switch fd.FullName() { case "poktroll.tokenomics.EventApplicationOverserviced.application_addr": return protoreflect.ValueOfString("") + case "poktroll.tokenomics.EventApplicationOverserviced.supplier_addr": + return protoreflect.ValueOfString("") case "poktroll.tokenomics.EventApplicationOverserviced.expected_burn": m := new(v1beta1.Coin) return protoreflect.ValueOfMessage(m.ProtoReflect()) @@ -2135,6 +2156,10 @@ func (x *fastReflection_EventApplicationOverserviced) ProtoMethods() *protoiface if l > 0 { n += 1 + l + runtime.Sov(uint64(l)) } + l = len(x.SupplierAddr) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } if x.ExpectedBurn != nil { l = options.Size(x.ExpectedBurn) n += 1 + l + runtime.Sov(uint64(l)) @@ -2184,7 +2209,7 @@ func (x *fastReflection_EventApplicationOverserviced) ProtoMethods() *protoiface copy(dAtA[i:], encoded) i = runtime.EncodeVarint(dAtA, i, uint64(len(encoded))) i-- - dAtA[i] = 0x1a + dAtA[i] = 0x22 } if x.ExpectedBurn != nil { encoded, err := options.Marshal(x.ExpectedBurn) @@ -2198,6 +2223,13 @@ func (x *fastReflection_EventApplicationOverserviced) ProtoMethods() *protoiface copy(dAtA[i:], encoded) i = runtime.EncodeVarint(dAtA, i, uint64(len(encoded))) i-- + dAtA[i] = 0x1a + } + if len(x.SupplierAddr) > 0 { + i -= len(x.SupplierAddr) + copy(dAtA[i:], x.SupplierAddr) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.SupplierAddr))) + i-- dAtA[i] = 0x12 } if len(x.ApplicationAddr) > 0 { @@ -2289,6 +2321,38 @@ func (x *fastReflection_EventApplicationOverserviced) ProtoMethods() *protoiface x.ApplicationAddr = 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 SupplierAddr", 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.SupplierAddr = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: if wireType != 2 { return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field ExpectedBurn", wireType) } @@ -2324,7 +2388,7 @@ func (x *fastReflection_EventApplicationOverserviced) ProtoMethods() *protoiface return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err } iNdEx = postIndex - case 3: + case 4: if wireType != 2 { return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field EffectiveBurn", wireType) } @@ -3277,16 +3341,24 @@ func (x *EventRelayMiningDifficultyUpdated) GetNewNumRelaysEma() uint64 { return 0 } -// EventApplicationOverserviced is emitted when an application has less stake -// than the expected burn. +// EventApplicationOverserviced is emitted when an application has less stake than +// what a supplier is claiming (i.e. burn is not high enough). type EventApplicationOverserviced struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - ApplicationAddr string `protobuf:"bytes,1,opt,name=application_addr,json=applicationAddr,proto3" json:"application_addr,omitempty"` - ExpectedBurn *v1beta1.Coin `protobuf:"bytes,2,opt,name=expected_burn,json=expectedBurn,proto3" json:"expected_burn,omitempty"` - EffectiveBurn *v1beta1.Coin `protobuf:"bytes,3,opt,name=effective_burn,json=effectiveBurn,proto3" json:"effective_burn,omitempty"` + ApplicationAddr string `protobuf:"bytes,1,opt,name=application_addr,json=applicationAddr,proto3" json:"application_addr,omitempty"` + SupplierAddr string `protobuf:"bytes,2,opt,name=supplier_addr,json=supplierAddr,proto3" json:"supplier_addr,omitempty"` + // Expected burn is the amount the supplier is claiming for work done + // to service the application during the session. + // This is usually the amount in the Claim object. + ExpectedBurn *v1beta1.Coin `protobuf:"bytes,3,opt,name=expected_burn,json=expectedBurn,proto3" json:"expected_burn,omitempty"` + // Effective burn is the amount that is actually being paid to the supplier + // for the work done. It is less than the expected burn (claim amount) and + // most likely equal to the application's stake divided by the number of suppliers + // in a session. + EffectiveBurn *v1beta1.Coin `protobuf:"bytes,4,opt,name=effective_burn,json=effectiveBurn,proto3" json:"effective_burn,omitempty"` } func (x *EventApplicationOverserviced) Reset() { @@ -3316,6 +3388,13 @@ func (x *EventApplicationOverserviced) GetApplicationAddr() string { return "" } +func (x *EventApplicationOverserviced) GetSupplierAddr() string { + if x != nil { + return x.SupplierAddr + } + return "" +} + func (x *EventApplicationOverserviced) GetExpectedBurn() *v1beta1.Coin { if x != nil { return x.ExpectedBurn @@ -3460,50 +3539,53 @@ var file_poktroll_tokenomics_event_proto_rawDesc = []byte{ 0x65, 0x6c, 0x61, 0x79, 0x73, 0x45, 0x6d, 0x61, 0x12, 0x2b, 0x0a, 0x12, 0x6e, 0x65, 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x5f, 0x65, 0x6d, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6e, 0x65, 0x77, 0x4e, 0x75, 0x6d, 0x52, 0x65, 0x6c, 0x61, - 0x79, 0x73, 0x45, 0x6d, 0x61, 0x22, 0xcb, 0x01, 0x0a, 0x1c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x41, + 0x79, 0x73, 0x45, 0x6d, 0x61, 0x22, 0xf0, 0x01, 0x0a, 0x1c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x64, 0x12, 0x29, 0x0a, 0x10, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x64, 0x64, - 0x72, 0x12, 0x3e, 0x0a, 0x0d, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x75, - 0x72, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, - 0x6f, 0x69, 0x6e, 0x52, 0x0c, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x42, 0x75, 0x72, - 0x6e, 0x12, 0x40, 0x0a, 0x0e, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x62, - 0x75, 0x72, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, - 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, - 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x0d, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x42, - 0x75, 0x72, 0x6e, 0x22, 0xc2, 0x01, 0x0a, 0x24, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x41, 0x70, 0x70, - 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x69, 0x6d, 0x62, 0x75, 0x72, 0x73, - 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x10, - 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x64, 0x64, 0x72, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x31, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, - 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, - 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x2a, 0x60, 0x0a, 0x15, 0x43, 0x6c, 0x61, 0x69, - 0x6d, 0x45, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x61, 0x73, 0x6f, - 0x6e, 0x12, 0x21, 0x0a, 0x1d, 0x45, 0x58, 0x50, 0x49, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, - 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, - 0x45, 0x44, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x4d, 0x49, - 0x53, 0x53, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x52, 0x4f, 0x4f, 0x46, - 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x02, 0x42, 0xb8, 0x01, 0x0a, 0x17, 0x63, - 0x6f, 0x6d, 0x2e, 0x70, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2e, 0x74, 0x6f, 0x6b, 0x65, - 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0x42, 0x0a, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x24, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, - 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2f, - 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0xa2, 0x02, 0x03, 0x50, 0x54, 0x58, - 0xaa, 0x02, 0x13, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2e, 0x54, 0x6f, 0x6b, 0x65, - 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0xca, 0x02, 0x13, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, - 0x6c, 0x5c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0xe2, 0x02, 0x1f, 0x50, - 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x5c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, - 0x63, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, - 0x14, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x3a, 0x3a, 0x54, 0x6f, 0x6b, 0x65, 0x6e, - 0x6f, 0x6d, 0x69, 0x63, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x5f, 0x61, 0x64, + 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x69, + 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x12, 0x3e, 0x0a, 0x0d, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, + 0x65, 0x64, 0x5f, 0x62, 0x75, 0x72, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, + 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, + 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x0c, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, + 0x65, 0x64, 0x42, 0x75, 0x72, 0x6e, 0x12, 0x40, 0x0a, 0x0e, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, + 0x69, 0x76, 0x65, 0x5f, 0x62, 0x75, 0x72, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, + 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, + 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x0d, 0x65, 0x66, 0x66, 0x65, 0x63, + 0x74, 0x69, 0x76, 0x65, 0x42, 0x75, 0x72, 0x6e, 0x22, 0xc2, 0x01, 0x0a, 0x24, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x69, + 0x6d, 0x62, 0x75, 0x72, 0x73, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x29, 0x0a, 0x10, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x61, 0x70, 0x70, + 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x12, 0x1d, 0x0a, 0x0a, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x31, 0x0a, 0x06, 0x61, 0x6d, + 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, + 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x2a, 0x60, 0x0a, + 0x15, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x45, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x1d, 0x45, 0x58, 0x50, 0x49, 0x52, 0x41, + 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, + 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x52, 0x4f, + 0x4f, 0x46, 0x5f, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, + 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x02, 0x42, + 0xb8, 0x01, 0x0a, 0x17, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, + 0x2e, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0x42, 0x0a, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x24, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x6f, 0x6b, 0x74, + 0x72, 0x6f, 0x6c, 0x6c, 0x2f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0xa2, + 0x02, 0x03, 0x50, 0x54, 0x58, 0xaa, 0x02, 0x13, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, + 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0xca, 0x02, 0x13, 0x50, 0x6f, + 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x5c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, + 0x73, 0xe2, 0x02, 0x1f, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x5c, 0x54, 0x6f, 0x6b, + 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0xea, 0x02, 0x14, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x3a, 0x3a, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( diff --git a/docusaurus/docs/protocol/tokenomics/resources.md b/docusaurus/docs/protocol/tokenomics/resources.md index 9b31e6ec1..b652b0349 100644 --- a/docusaurus/docs/protocol/tokenomics/resources.md +++ b/docusaurus/docs/protocol/tokenomics/resources.md @@ -5,10 +5,13 @@ sidebar_position: 1 # Tokenomics Resources -The following resources serve as the foundation for the Shannon Upgrade Tokenomics. +:::warning + +This is an active an ever evolving work. We are working on a single source of truth. -It is an active an ever evolving work, but the following resources are the best -starting references: +::: + +The following resources serve as the foundation for the Shannon Upgrade Tokenomics. - [Token Logic Module](https://docs.pokt.network/pokt-protocol/the-shannon-upgrade/proposed-tokenomics/token-logic-modules) design approach. - [Shannon Tokenomics Static](https://github.com/pokt-network/shannon-tokenomics-static-tests) modeling & evaluation diff --git a/docusaurus/docs/protocol/tokenomics/token_logic_modules.md b/docusaurus/docs/protocol/tokenomics/token_logic_modules.md index 3fd36ddd0..fd70d0fe9 100644 --- a/docusaurus/docs/protocol/tokenomics/token_logic_modules.md +++ b/docusaurus/docs/protocol/tokenomics/token_logic_modules.md @@ -6,8 +6,8 @@ sidebar_position: 2 # Token Logic Modules - [Introduction](#introduction) -- [Background: Relay Mining Payable Relay Accumulation](#background-relay-mining-payable-relay-accumulation) -- [TLM Pre-processor: Claim Settlement Limit](#tlm-pre-processor-claim-settlement-limit) +- [Background: Max Claimable Amount](#background-max-claimable-amount) +- [TLM (pre) Processing](#tlm-pre-processing) - [TLM: Mint=Burn (MEB)](#tlm-mintburn-meb) - [TLM: Global Mint (GM)](#tlm-global-mint-gm) - [TLM: Global Mint Reimbursement Request (GMRR)](#tlm-global-mint-reimbursement-request-gmrr) @@ -22,50 +22,58 @@ Note that this is an active WIP and the [resources here](./resources.md) are the Token Logic Modules (TLMs) processing involves: -1. `TLM pre-processing` - A general pre-processor determining the amount of coins to settle per claim -2. `TLM processing` - Individual processing each TLM independent of the other +1. `TLM pre-processing` - A general pre-processor determining the amount of tokens to settle per claim. +2. `TLM processing` - Iteration through all of the TLMs one by one. +3. `TLM processor` - Individual processing each TLM independent of one another. -## Background: Relay Mining Payable Relay Accumulation +## Background: Max Claimable Amount + +_tl;dr Max Claimable Amount ∝ (Application Stake / Number of Suppliers per Session)_ Per **Algorithm 1** of the [Relay Mining paper](https://arxiv.org/pdf/2305.10672), the maximum amount a supplier can claim from an application in a single session is -proportional to the Application's stake divided by the number of nodes in the session -as see in the following image: +proportional to the Application's stake divided by the number of suppliers in the session. + +This is referred to as "Relay Mining Payable Relay Accumulation" in the paper and +can be seen in the following image: ![Algorithm 1](https://github.com/user-attachments/assets/d1a61535-aa31-447d-88ea-c8d14dcb20c6) -## TLM Pre-processor: Claim Settlement Limit +## TLM (pre) Processing + +_tl;dr Determine if the claim settlement amount is greater than the maximum claimable amount and then run each individual TLM._ **Prior to** processing each individual TLM, we need to understand if the amount claimed -by the supplier adheres to the maximum allowed per the limits set by Relay Mining. +by the supplier adheres to the optimistic maxima set per the limits of Relay Mining. Suppliers always have the option to over-service an application (**i.e. do free work**), -in exchange for providing a good service to the network, but their on-chain rewards +in exchange for providing a good service to the network. This may lead to offchain +reputation benefits (e.g. Gateways favoring them), but their on-chain rewards are still limited as a function of the application's stake before the session started -and the number of nodes in the session. +and the number of suppliers in the session. :::note TODO_POST_MAINNET: After the Shannon upgrade, the team at Grove has a lot of ideas -related to [supplier gossipin](https://www.notion.so/buildwithgrove/Off-chain-Application-Stake-Tracking-6a8bebb107db4f7f9dc62cbe7ba555f7?pvs=4) but that -is out of scope for the initial implementation. +related to on-chain reputation, [supplier gossiping](https://www.notion.so/buildwithgrove/Off-chain-Application-Stake-Tracking-6a8bebb107db4f7f9dc62cbe7ba555f7?pvs=4), and +much more, but that is out of scope for the initial implementation. ::: ```mermaid --- -title: "Token Logic Modules Processor" +title: "Token Logic Modules (pre) Processing" --- flowchart TB CSA(["Claim Settlement Amount (CSA)"]) - MCS(["MaxClaimPerSupplier (MCS)
= (AppStake / NumNodesPerSession)"]) - CC{"Is CSA > MCS?"} - Update(Set SA = MCS
Broadcast Event) + MCA(["MaxClaimPerSupplier (MCA)
= (AppStake / NumSuppliersPerSession)"]) + CC{"Is CSA > MCA?"} + Update(Set SA = MCA
Broadcast Event) SOAE{{Application Overserviced
Event}} TLMP[["TLM Processor (SA)"]] CSA -- CSA --> CC - MCS -- MCS --> CC + MCA -- MCA --> CC Update -..-> SOAE CC -- Yes --> Update @@ -74,7 +82,7 @@ flowchart TB TLMP --SA--> TLMBEM[[TLM: Burn Equals Mint]] TLMP --SA--> TLMGI[[TLM: Global Inflation]] - TLMP --SA--> TLMGIRR[[TLM: Global Inflation Reimbursment Request]] + TLMP --SA--> TLMGIRR[[TLM: Global Inflation Reimbursement Request]] classDef tlm fill:#54ebd5,stroke:#333,stroke-width:2px; classDef question fill:#e3db6d,stroke:#333,stroke-width:2px; @@ -87,15 +95,14 @@ flowchart TB ## TLM: Mint=Burn (MEB) +_tl;dr The transfer of tokens from the application to the supplier based on the amount of work received and provided respectively.._ + The `Mint=Burn` TLM is, _theoretically_, the only TLM necessary when the network reaches equilibrium in the far future. -Put simply, it is a transfer of tokens from the application to the supplier based on the -amount of work done by the supplier. - -The same amount of tokens that is minted in the supplier module is burned from the application module. -The stake of the application paying for work is reduced and the rewards are distributed to the supplier -and its revenue shareholder addresses. +The same amount of tokens that is minted in the **supplier module** is burned from +the **application module**. The stake of the application paying for work is reduced +and the rewards are distributed to the supplier and its revenue shareholder addresses. ```mermaid --- @@ -127,12 +134,12 @@ flowchart TD AA[Application Address] AM -.- AK - AK -. Reduce Stake by CSA .-> AA + AK -. Reduce Stake by SA .-> AA + AA -.- TODO{See TODO below} end SM --> SD - classDef module fill:#f9f,stroke:#333,stroke-width:2px; classDef address fill:#bbf,stroke:#333,stroke-width:2px; classDef question fill:#e3db6d,stroke:#333,stroke-width:2px; @@ -140,18 +147,141 @@ flowchart TD class SM,AM module; class RSA,OA,OPA,AA address; + class TODO question; ``` +:::note + +TODO_MAINNET: If the application stake has dropped to (near?) zero, should +we unstake it? Should we use it's balance? Should their be a payee of last resort? +Make sure to document whatever decision we come to. + +::: + ## TLM: Global Mint (GM) -TLMGlobalMint is the token logic module that mints new tokens based on the -on global governance parameters in order to reward the participants providing -services while keeping inflation in check. +_tl;dr Distributed newly minted coins on a per claim basis to all involved stakeholders._ + +The `Global Mint` TLM is, _theoretically_, going to reach `zero`the only when the network +reaches equilibrium in the far future. + +On a per claim basis, the network mints new tokens based on the the amount of work +claimed. The newly minted tokens are distributed to the supplier, DAO, service owner +and application based on the values of various governance params. + +```mermaid +--- +title: "Token Logic Module: Global Mint" +--- +flowchart TD + SC(["Settlement Coin (SC)"]) + PCI(["Per Claim Global Inflation
(Governance Parameter)"]) + IMC(["Inflation Mint Coin (IMC)"]) + + DA(["DAO Mint Allocation"]) + PA(["Proposer Mint Allocation"]) + SA(["Supplier Mint Allocation"]) + SOA(["Source Owner Mint Allocation"]) + AA(["Application Mint Allocation"]) + + + SC --> IMC + PCI --> IMC + IMC --> TO + + subgraph TO[Tokenomics Operations] + TM[[Tokenomics Module]] + TK[(Tokenomics Keeper)] + TM -..- TK + end + + + DA --> ID + PA --> ID + TO -- New Mint Coin (NMC)--> ID + SA --> ID + AA --> ID + + subgraph ID[Inflation Distribution] + NMC["New Mint Coin (NMC)"] + APPA["Application Address"] + SPPA["Supplier Address"] + DAOA["DAO Address"] + SOA["Service Owner Address"] + PRA["Proposer Address"] + + NMC -->|% Mint Allocation| APPA + NMC -->|% Mint Allocation| SPPA + NMC -->|% Mint Allocation| DAOA + NMC -->|% Mint Allocation| SOA + NMC -->|% Mint Allocation| PRA + end + + classDef module fill:#f9f,stroke:#333,stroke-width:2px; + classDef address fill:#bbf,stroke:#333,stroke-width:2px; + classDef question fill:#e3db6d,stroke:#333,stroke-width:2px; + classDef govparam fill:#d04a36,stroke:#333,stroke-width:2px; + classDef event fill:#e8b761,stroke:#333,stroke-width:2px; + + class TM module; + class PCI,DA,PA,SA,AA govparam; + class APPA,SPPA,DAOA,SOA,PRA address; +``` ## TLM: Global Mint Reimbursement Request (GMRR) -TLMGlobalMintReimbursementRequest is the token logic module that complements -TLMGlobalMint to enable permissionless demand. In order to prevent self-dealing -attacks, applications will be overcharged by the amount equal to global inflation, -those funds will be sent to the DAO/PNF, and event will be emitted to be used -for reimbursements. +_tl;dr Prevent self-dealing by over-charging applications, sending the excess to the DAO/PNF, and emitting an event as a reimbursement request._ + +This TLM **MUST** be processed alongside the Global Mint TLM. + +This TLM can, **theoretically**, be removed if self-dealing attacks are not a concern, +or if the global mint per claim governance parameter is set to zero. + +The goal of the TLM is to overcharge applications equal to the global inflation amount +and send those funds to the DAO/PNF. This forces potentially self-dealing gateways to +"show face" in front of the DAO/PNF and request reimbursement. + +The event emitted creates an easy, onchain mechanism, to track reimbursement handled offchain. + +A side effect of this TLM is creating additional buy pressure of the token as Applications +and Gateways will be responsible for frequently "topping up" their balances and app stakes. + +```mermaid +--- +title: "Token Logic Module: Global Mint Reimbursement Request" +--- +flowchart TD + SC(["Settlement Coin (SC)"]) + PCI(["Per Claim Global Inflation
(Governance Parameter)"]) + IMC(["Inflation Mint Coin (IMC)"]) + ARRE{{Application Reimbursement
Request Event}} + + SC --> IMC + PCI --> IMC + IMC --IMC--> AO + + + subgraph AO[Application Operations] + AM[[Application Module]] + AK[(Application Keeper)] + AA[Application Address] + DA[DAO Address] + + AM -.- AK + AK -. Reduce Stake by IMC .-> AA + AM -..-> |Increase Balance by IMC| DA + end + + AO -. Emit Event.-> ARRE + + classDef module fill:#f9f,stroke:#333,stroke-width:2px; + classDef address fill:#bbf,stroke:#333,stroke-width:2px; + classDef question fill:#e3db6d,stroke:#333,stroke-width:2px; + classDef govparam fill:#d04a36,stroke:#333,stroke-width:2px; + classDef event fill:#e8b761,stroke:#333,stroke-width:2px; + + class AM module; + class ARRE event; + class PCI govparam; + class AA,DA address; +``` diff --git a/proto/poktroll/tokenomics/event.proto b/proto/poktroll/tokenomics/event.proto index 00a089f8f..e7f698aea 100644 --- a/proto/poktroll/tokenomics/event.proto +++ b/proto/poktroll/tokenomics/event.proto @@ -49,18 +49,17 @@ message EventRelayMiningDifficultyUpdated { message EventApplicationOverserviced { string application_addr = 1; string supplier_addr = 2; + // Expected burn is the amount the supplier is claiming for work done + // to service the application during the session. + // This is usually the amount in the Claim object. cosmos.base.v1beta1.Coin expected_burn = 3; + // Effective burn is the amount that is actually being paid to the supplier + // for the work done. It is less than the expected burn (claim amount) and + // most likely equal to the application's stake divided by the number of suppliers + // in a session. cosmos.base.v1beta1.Coin effective_burn = 4; } -// EventSupplierExceededClaimableAmount is emitted when a supplier application has less stake -// than the expected burn. -message EventSupplierExceededClaimableAmount { - string supplier_addr = 1; - cosmos.base.v1beta1.Coin expected_burn = 2; - cosmos.base.v1beta1.Coin effective_burn = 3; -} - // EventApplicationReimbursementRequest is emitted when an application requests // a reimbursement message EventApplicationReimbursementRequest { diff --git a/x/session/keeper/session_hydrator.go b/x/session/keeper/session_hydrator.go index 60c292836..bf7420e6d 100644 --- a/x/session/keeper/session_hydrator.go +++ b/x/session/keeper/session_hydrator.go @@ -20,8 +20,8 @@ import ( var SHA3HashLen = crypto.SHA3_256.Size() -// TODO_BLOCKER(@bryanchriswhite, #21): Make these configurable governance param const ( + // TODO_BETA(@bryanchriswhite): Make this a governance parameter NumSupplierPerSession = 15 SessionIDComponentDelimiter = "." ) diff --git a/x/session/keeper/session_hydrator_test.go b/x/session/keeper/session_hydrator_test.go index d70c148b7..f0b3cf0ad 100644 --- a/x/session/keeper/session_hydrator_test.go +++ b/x/session/keeper/session_hydrator_test.go @@ -289,7 +289,7 @@ func TestSession_HydrateSession_Application(t *testing.T) { // TODO_TEST: Expand these tests to account for supplier joining/leaving the network at different heights as well changing the services they support func TestSession_HydrateSession_Suppliers(t *testing.T) { - // TODO_TEST: Extend these tests once `NumBlocksPerSession` is configurable. + // TODO_BETA(@bryanchriswhite): Extend these tests once `NumBlocksPerSession` is configurable. // Currently assumes NumSupplierPerSession=15 tests := []struct { // Description diff --git a/x/shared/types/service.pb.go b/x/shared/types/service.pb.go index 3bbb2d31d..22ed750a8 100644 --- a/x/shared/types/service.pb.go +++ b/x/shared/types/service.pb.go @@ -93,7 +93,7 @@ func (ConfigOptions) EnumDescriptor() ([]byte, []int) { type Service struct { // For example, what if we want to request a session for a certain service but with some additional configs that identify it? Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - // TODO_MAINNET: Remove this. + // TODO_BETA: Either remove this or rename it to alias. Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` // The cost of a single relay for this service in terms of compute units. // Must be used alongside the global 'compute_units_to_tokens_multipler' to calculate the cost of a relay for this service. @@ -169,7 +169,7 @@ func (m *Service) GetOwnerAddress() string { // ApplicationServiceConfig holds the service configuration the application stakes for type ApplicationServiceConfig struct { - // TODO_MAINNET: Avoid embedding the full Service because we just need the ID. + // TODO_BETA: Avoid embedding the full Service because we just need the ID. Service *Service `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"` } @@ -215,7 +215,7 @@ func (m *ApplicationServiceConfig) GetService() *Service { // SupplierServiceConfig holds the service configuration the supplier stakes for type SupplierServiceConfig struct { - // TODO_MAINNET: Avoid embedding the full Service because we just need the ID. + // TODO_BETA: Avoid embedding the full Service because we just need the ID. Service *Service `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"` Endpoints []*SupplierEndpoint `protobuf:"bytes,2,rep,name=endpoints,proto3" json:"endpoints,omitempty"` RevShare []*ServiceRevenueShare `protobuf:"bytes,3,rep,name=rev_share,json=revShare,proto3" json:"rev_share,omitempty"` diff --git a/x/tokenomics/keeper/token_logic_modules.go b/x/tokenomics/keeper/token_logic_modules.go index 99cff2611..a05b1aee2 100644 --- a/x/tokenomics/keeper/token_logic_modules.go +++ b/x/tokenomics/keeper/token_logic_modules.go @@ -1,14 +1,11 @@ package keeper -// References: -// - https://docs.pokt.network/pokt-protocol/the-shannon-upgrade/proposed-tokenomics/token-logic-modules -// - https://github.com/pokt-network/shannon-tokenomics-static-tests - import ( "context" "fmt" "math/big" + "cosmossdk.io/log" "cosmossdk.io/math" cosmostypes "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -19,6 +16,7 @@ import ( "github.com/pokt-network/poktroll/telemetry" apptypes "github.com/pokt-network/poktroll/x/application/types" prooftypes "github.com/pokt-network/poktroll/x/proof/types" + sessionkeeper "github.com/pokt-network/poktroll/x/session/keeper" sessiontypes "github.com/pokt-network/poktroll/x/session/types" sharedtypes "github.com/pokt-network/poktroll/x/shared/types" suppliertypes "github.com/pokt-network/poktroll/x/supplier/types" @@ -28,11 +26,12 @@ import ( const ( // Governance parameters for the TLMGlobalMint module - // TODO_UPNEXT(@olshansk): Remove this. An ephemeral placeholder before + // TODO_BETA_TEST(@olshansk): Remove this. It is an ephemeral placeholder before // real values are introduced. When this is changed to a governance param, // make sure to also add the necessary unit tests. - MintGlobalInflation = 0.0000000 - // TODO_UPNEXT(@olshansk): Make all of the governance params + MintPerClaimGlobalInflation = 0.0000000 + + // TODO_BETA: Make all of the governance params MintAllocationDAO = 0.1 MintAllocationProposer = 0.05 MintAllocationSupplier = 0.7 @@ -44,8 +43,8 @@ type TokenLogicModule int const ( // TLMRelayBurnEqualsMint is the token logic module that burns the application's - // stake based on the amount of work done by the supplier. The same amount of - // tokens is minted and sent to the supplier. + // stake based on the amount of work done by the supplier. + // The same amount of tokens is minted and sent to the supplier. // When the network achieves equilibrium, this is theoretically the only TLM that will be necessary. TLMRelayBurnEqualsMint TokenLogicModule = iota @@ -57,8 +56,8 @@ const ( // TLMGlobalMintReimbursementRequest is the token logic module that complements // TLMGlobalMint to enable permissionless demand. In order to prevent self-dealing // attacks, applications will be overcharged by the amount equal to global inflation, - // those funds will be sent to the DAO/PNF, and event will be emitted to be used - // for reimbursements. + // those funds will be sent to the DAO/PNF, and an event will be emitted to track + // and send reimbursements; managed offchain by PNF. // TODO_POST_MAINNET: Introduce proper tokenomics based on the research done by @rawthil and @shane. TLMGlobalMintReimbursementRequest ) @@ -79,10 +78,10 @@ func (tlm TokenLogicModule) EnumIndex() int { // TokenLogicModuleProcessor is the method signature that all token logic modules // are expected to implement. -// IMPORTANT SIDE EFFECTS: Please note that TLMS may update the application and supplier -// objects, which is why they are passed in as pointers. However, this IS NOT persisted. -// The persistence to the keeper is currently done by ProcessTokenLogicModules only. -// This may be an interim state of the implementation and may change in the future. +// IMPORTANT_SIDE_EFFECTS: Please note that TLMs may update the application and supplier +// objects, which is why they are passed in as pointers. NOTE THAT THIS IS NOT PERSISTED. +// The persistence to the keeper is currently done by the TLM processor: ProcessTokenLogicModules. +// This design and separation of concerns may change in the future. type TokenLogicModuleProcessor func( Keeper, context.Context, @@ -94,10 +93,11 @@ type TokenLogicModuleProcessor func( *tokenomictypes.RelayMiningDifficulty, ) error -// tokenLogicModuleProcessorMap is a map of token logic modules to their respective processors. +// tokenLogicModuleProcessorMap is a map of TLMs to their respective independent processors. var tokenLogicModuleProcessorMap = map[TokenLogicModule]TokenLogicModuleProcessor{ TLMRelayBurnEqualsMint: Keeper.TokenLogicModuleRelayBurnEqualsMint, TLMGlobalMint: Keeper.TokenLogicModuleGlobalMint, + // TODO_BETA_UPNEXT(@Olshansky): Uncomment this and add tests. // TLMGlobalMintReimbursementRequest: Keeper.TokenLogicModuleGlobalMintReimbursementRequest, } @@ -108,16 +108,18 @@ func init() { } } -// ProcessTokenLogicModules is the main TLM processor. It is responsible for calling -// all of the token logic module necessary to limit, burn, mint or transfer tokens -// as a result of the amount of work (i.e. compute units) done and governance parameters. +// ProcessTokenLogicModules is the main TLM processor. It is responsible for running +// all of the independent TLMs necessary to limit, burn, mint or transfer tokens +// as a result of the amount of work (i.e. relays, compute units) done in proportion +// to the global governance parameters. +// IMPORTANT: It is assumed the proof for the claim has been validated BEFORE calling this function. func (k Keeper) ProcessTokenLogicModules( ctx context.Context, - claim *prooftypes.Claim, // IMPORTANT: It is assumed the proof for the claim has been validated BEFORE calling this function + claim *prooftypes.Claim, ) (err error) { logger := k.Logger().With("method", "ProcessTokenLogicModules") - // Declaring variables that will be emitted by telemetry + // Telemetry variable declaration to be emitted a the end of the function claimSettlementCoin := cosmostypes.NewCoin("upokt", math.NewInt(0)) isSuccessful := false @@ -133,7 +135,7 @@ func (k Keeper) ProcessTokenLogicModules( func() bool { return isSuccessful }, ) - // Ensure the claim is not nil + // Sanity check the claim is not nil. Validation of the claim is expected by the caller. if claim == nil { logger.Error("received a nil claim") return tokenomicstypes.ErrTokenomicsClaimNil @@ -150,22 +152,8 @@ func (k Keeper) ProcessTokenLogicModules( return tokenomicstypes.ErrTokenomicsSessionHeaderInvalid } - // Retrieve the supplier operator address that will be getting rewarded; providing services - supplierOperatorAddr, err := cosmostypes.AccAddressFromBech32(claim.GetSupplierOperatorAddress()) - if err != nil || supplierOperatorAddr == nil { - return tokenomicstypes.ErrTokenomicsSupplierOperatorAddressInvalid - } - - // Retrieve the application address that is being charged; getting services - applicationAddress, err := cosmostypes.AccAddressFromBech32(sessionHeader.GetApplicationAddress()) - if err != nil || applicationAddress == nil { - return tokenomicstypes.ErrTokenomicsApplicationAddressInvalid - } - - // Retrieve the root of the claim to determine the amount of work done + // Retrieve and validate the root of the claim to determine the amount of work done root := (smt.MerkleSumRoot)(claim.GetRootHash()) - - // Ensure the root hash is valid if !root.HasDigestSize(protocol.TrieHasherSize) { return tokenomicstypes.ErrTokenomicsRootHashInvalid.Wrapf( "root hash has invalid digest size (%d), expected (%d)", @@ -173,6 +161,29 @@ func (k Keeper) ProcessTokenLogicModules( ) } + // Retrieve the count (i.e. number of relays) to determine the amount of work done + numRelays, err := root.Count() + if err != nil { + return tokenomicstypes.ErrTokenomicsRootHashInvalid.Wrapf("%v", err) + } + + /* + TODO_POST_MAINNET: Because of how things have evolved, we are now using + root.Count (numRelays) instead of root.Sum (numComputeUnits) to determine + the amount of work done. This is because the compute_units_per_relay is + a service specific (not request specific) parameter that will be maintained + by the service owner to capture the average amount of resources (i.e. + compute, storage, bandwidth, electricity, etc...) per request. Modifying + this on a per request basis has been deemed too complex and not a mainnet + blocker. + */ + + // Retrieve the application address that is being charged; getting services and paying tokens + applicationAddress, err := cosmostypes.AccAddressFromBech32(sessionHeader.GetApplicationAddress()) + if err != nil || applicationAddress == nil { + return tokenomicstypes.ErrTokenomicsApplicationAddressInvalid + } + // Retrieve the on-chain staked application record application, isAppFound := k.applicationKeeper.GetApplication(ctx, applicationAddress.String()) if !isAppFound { @@ -180,6 +191,12 @@ func (k Keeper) ProcessTokenLogicModules( return tokenomicstypes.ErrTokenomicsApplicationNotFound } + // Retrieve the supplier operator address that will be getting rewarded; providing services and earning tokens + supplierOperatorAddr, err := cosmostypes.AccAddressFromBech32(claim.GetSupplierOperatorAddress()) + if err != nil || supplierOperatorAddr == nil { + return tokenomicstypes.ErrTokenomicsSupplierOperatorAddressInvalid + } + // Retrieve the on-chain staked supplier record supplier, isSupplierFound := k.supplierKeeper.GetSupplier(ctx, supplierOperatorAddr.String()) if !isSupplierFound { @@ -187,48 +204,20 @@ func (k Keeper) ProcessTokenLogicModules( return tokenomicstypes.ErrTokenomicsSupplierNotFound } + // Retrieve the service that the supplier is providing service, isServiceFound := k.serviceKeeper.GetService(ctx, sessionHeader.Service.Id) if !isServiceFound { return tokenomicstypes.ErrTokenomicsServiceNotFound.Wrapf("service with ID %q not found", sessionHeader.Service.Id) } - // Retrieve the count (i.e. number of relays) to determine the amount of work done - numRelays, err := root.Count() - if err != nil { - return tokenomicstypes.ErrTokenomicsRootHashInvalid.Wrapf("%v", err) - } - - // TODO_POST_MAINNET: Because of how things have evolved, we are now using - // root.Count (numRelays) instead of root.Sum (numComputeUnits) to determine - // the amount of work done. This is because the compute_units_per_relay is - /// a service specific (not request specific) parameter that will be maintained - // by the service owner to capture the average amount of resources (i.e. - // compute, storage, bandwidth, electricity, etc...) per request. Modifying - // this on a per request basis has been deemed too complex and not a mainnet - // blocker. - - // Determine the total number of tokens that'll be used for settling the session. - // When the network achieves equilibrium, this will be the mint & burn. + // Determine the total number of tokens being claimed (i.e. requested) + // by the supplier for the amount of work they did to service the application + // in the session. claimSettlementCoin, err = k.numRelaysToCoin(ctx, numRelays, &service) if err != nil { return err } - // Retrieving the relay mining difficulty for the service at hand - relayMiningDifficulty, found := k.GetRelayMiningDifficulty(ctx, service.Id) - if !found { - if err != nil { - return err - } - logger.Warn(fmt.Sprintf("relay mining difficulty for service %q not found. Using default difficulty", service.Id)) - relayMiningDifficulty = tokenomicstypes.RelayMiningDifficulty{ - ServiceId: service.Id, - BlockHeight: sdk.UnwrapSDKContext(ctx).BlockHeight(), - NumRelaysEma: numRelays, - TargetHash: prooftypes.DefaultRelayDifficultyTargetHash, - } - } - // Helpers for logging the same metadata throughout this function calls logger = logger.With( "num_relays", numRelays, @@ -238,37 +227,40 @@ func (k Keeper) ProcessTokenLogicModules( "supplier_operator", supplier.OperatorAddress, "application", application.Address, ) - logger.Info(fmt.Sprintf("About to start processing TLMs for (%d) relays equaling to (%s) upokt claimed", numRelays, claimSettlementCoin)) - maxClaimableAmount := application.GetStake().QuoUint64(uint64(relayMiningDifficulty.NumNodesPerSession)) + // Retrieving the relay mining difficulty for the service at hand + relayMiningDifficulty, found := k.GetRelayMiningDifficulty(ctx, service.Id) + if !found { + relayMiningDifficulty = newDefaultRelayMiningDifficulty(ctx, logger, service.Id, numRelays) + } - // Reduce the settlement amount if the application was over-serviced - var actualSettlementCoin cosmostypes.Coin - if application.GetStake().IsLT(claimSettlementCoin) { - actualSettlementCoin, err = k.handleOverservicedApplication(ctx, &application, claimSettlementCoin) - if err != nil { - return err - } - logger.Warn(fmt.Sprintf("Application with address %s was over-serviced so the actual amount being settled is (%v) instead of the claimed amount (%v) ", application.Address, actualSettlementCoin, claimSettlementCoin)) - } else { - actualSettlementCoin = claimSettlementCoin + // Ensure the claim amount is within the limits set by Relay Mining. + // Update the settlement amount if not and emit any necessary events in doing so. + actualSettlementCoin, err := k.ensureClaimAmountLimits(ctx, logger, &application, &supplier, claimSettlementCoin) + if err != nil { + return err } logger = logger.With("actual_settlement_upokt", actualSettlementCoin) + logger.Info(fmt.Sprintf("About to start processing TLMs for (%d) relays equaling to (%s) upokt claimed", numRelays, actualSettlementCoin)) // Execute all the token logic modules processors for tlm, tlmProcessor := range tokenLogicModuleProcessorMap { - logger.Info(fmt.Sprintf("Starting to execute TLM %q", tlm)) + logger.Info(fmt.Sprintf("Starting TLM processing: %q", tlm)) if err := tlmProcessor(k, ctx, &service, claim.SessionHeader, &application, &supplier, actualSettlementCoin, &relayMiningDifficulty); err != nil { return err } - logger.Info(fmt.Sprintf("Finished executing TLM %q", tlm)) + logger.Info(fmt.Sprintf("Finished TLM processing: %q", tlm)) } - // Update the application's on-chain record + // State mutation: update the application's on-chain record k.applicationKeeper.SetApplication(ctx, application) logger.Info(fmt.Sprintf("updated on-chain application record with address %q", application.Address)) - // Update the suppliers's on-chain record + // TODO_MAINNET: If the application stake has dropped to (near?) zero, should + // we unstake it? Should we use it's balance? Should their be a payee of last resort? + // Make sure to document whatever decision we come to. + + // State mutation: Update the suppliers's on-chain record k.supplierKeeper.SetSupplier(ctx, supplier) logger.Info(fmt.Sprintf("updated on-chain supplier record with address %q", supplier.OperatorAddress)) @@ -289,16 +281,16 @@ func (k Keeper) TokenLogicModuleRelayBurnEqualsMint( ) error { logger := k.Logger().With("method", "TokenLogicModuleRelayBurnEqualsMint") - ownerAddr, err := cosmostypes.AccAddressFromBech32(supplier.OwnerAddress) - if err != nil { - return err - } - // DEV_NOTE: We are doing a mint & burn + transfer, instead of a simple transfer // of funds from the supplier to the application in order to enable second // order economic effects with more optionality. This could include funds // going to pnf, delegators, enabling bonuses/rebates, etc... + ownerAddr, err := cosmostypes.AccAddressFromBech32(supplier.OwnerAddress) + if err != nil { + return err + } + // Mint new uPOKT to the supplier module account. // These funds will be transferred to the supplier below. if err = k.bankKeeper.MintCoins( @@ -312,8 +304,8 @@ func (k Keeper) TokenLogicModuleRelayBurnEqualsMint( } logger.Info(fmt.Sprintf("minted (%v) coins in the supplier module", settlementCoin)) - amount := settlementCoin.Amount.Uint64() - if err = k.distributeSupplierRewardsToShareHolders(ctx, ownerAddr.String(), service.Id, amount); err != nil { + // Distribute the rewards to the supplier's shareholders based on the rev share percentage. + if err = k.distributeSupplierRewardsToShareHolders(ctx, ownerAddr.String(), service.Id, settlementCoin.Amount.Uint64()); err != nil { return tokenomicstypes.ErrTokenomicsSupplierModuleMintFailed.Wrapf( "distributing rewards to supplier with operator address %s shareholders: %v", supplier.OperatorAddress, @@ -355,7 +347,7 @@ func (k Keeper) TokenLogicModuleGlobalMint( logger := k.Logger().With("method", "TokenLogicModuleGlobalMint") // Determine how much new uPOKT to mint based on global inflation - newMintCoins, newMintAmtFloat := calculateGlobalMintAllocationFromSettlementAmount(settlementCoin) + newMintCoins, newMintAmtFloat := calculateGlobalPerClaimMintInflationFromSettlementAmount(settlementCoin) // Mint new uPOKT to the tokenomics module account if err := k.bankKeeper.MintCoins(ctx, tokenomictypes.ModuleName, newMintCoins); err != nil { @@ -416,20 +408,7 @@ func (k Keeper) TokenLogicModuleGlobalMint( return nil } -// 1. Mint = Burn -// 2. Global Mint -// 4. Overcharge applications -// - Determine the amount send to suppliers -// - Determine the amount send to source owner -// - Overcharge application based on the sum of the two above -// - Send the overcharge to the PNF -// - Emit an event so we can track it -// - PNF manually reimburses the application at the end of the month -// - Prevents self dealing because application has to ask for reimbursement -// - Does not introduce friction to service owners getting rewarded -// - Does not introduce friction to suppliers getting rewarded -// - Ensure NewSession breaks if app stake is too low -// - Ensure relayminer has a toggle to prevent over charging +// TokenLogicModuleGlobalMintReimbursementRequest processes the business logic for the GlobalMintReimbursementRequest TLM. func (k Keeper) TokenLogicModuleGlobalMintReimbursementRequest( ctx context.Context, service *sharedtypes.Service, @@ -439,35 +418,29 @@ func (k Keeper) TokenLogicModuleGlobalMintReimbursementRequest( settlementCoins cosmostypes.Coin, relayMiningDifficulty *tokenomictypes.RelayMiningDifficulty, ) error { - // logger := k.Logger().With("method", "TokenLogicModuleGlobalMintReimbursementRequest") // Determine how much new uPOKT to mint based on global inflation - newMintCoins, _ := calculateGlobalMintAllocationFromSettlementAmount(settlementCoins) + newMintCoins, _ := calculateGlobalPerClaimMintInflationFromSettlementAmount(settlementCoins) + + /* + TODO_UPNEXT_BETA(@Olshansky): Finish implementing this: + 1. Overcharge the application (reduce stake and burn app module tokens) + 2. Send the overcharge to the DAO/PNF address + 3. Add extensive tests for this. + */ - // EventApplicationReimbursementRequest + // Prepare and emit the event for the application being overcharged reimbursementRequestEvent := tokenomictypes.EventApplicationReimbursementRequest{ ApplicationAddr: application.Address, ServiceId: service.Id, SessionId: sessionHeader.SessionId, Amount: &newMintCoins[0], } - eventManager := cosmostypes.UnwrapSDKContext(ctx).EventManager() if err := eventManager.EmitTypedEvent(&reimbursementRequestEvent); err != nil { - return tokenomicstypes.ErrTokenomicsApplicationReimbursementRequestFailed.Wrapf( - "application address: %s; service Id %s; session Id: %s; amount: %s", - application.GetAddress(), - service.Id, - sessionHeader.SessionId, - newMintCoins.String(), - ) + return tokenomicstypes.ErrTokenomicsEmittingEventFailed.Wrapf("error emitting event %v", reimbursementRequestEvent) } - // EventApplicationReimbursementRequest - // What if the application is overcharged? - // How do I enforce running both of them? - // Need to add a new governance parameter? - // Should we prevent new application sessions from starting if its too low? return nil } @@ -498,54 +471,64 @@ func (k Keeper) sendRewardsToAccount( return &coinToAcc, nil } -// handleOverservicedApplication handles the case where an application has been over-serviced. +// ensureClaimAmountLimits checks if the application was overserviced and handles +// the case if it was. // Per Algorithm #1 in the Relay Mining paper, the maximum amount that a single supplier -// can claim in a session is AppStake/NumNodesPerSession. -// If this is not the case, then the supplier essentially did "free work" and the actual -// claim amount is less than what was claimed. +// can claim in a session is AppStake/NumSuppliersPerSession. +// If this is not the case, then the supplier essentially did "free work" and the +// actual claim amount is less than what was claimed. // Ref: https://arxiv.org/pdf/2305.10672 -func (k Keeper) handleOverservicedApplication( +func (k Keeper) ensureClaimAmountLimits( ctx context.Context, + methodLogger log.Logger, application *apptypes.Application, + supplier *sharedtypes.Supplier, claimSettlementCoin cosmostypes.Coin, ) ( actualSettlementCoins cosmostypes.Coin, err error, ) { - logger := k.Logger().With("method", "handleOverservicedApplication") - logger.Warn(fmt.Sprintf( - "THIS SHOULD NEVER HAPPEN. Application with address %s needs to be charged more than it has staked: %v > %v", - application.Address, - claimSettlementCoin, - application.Stake, - )) - - // TODO_MAINNET(@Olshansk, @RawthiL): The application was over-serviced in the last session so it basically - // goes "into debt". Need to design a way to handle this when we implement - // probabilistic proofs and add all the parameter logic. Do we touch the application balance? - // Do we just let it go into debt? Do we penalize the application? Do we unstake it? Etc... - // See this document from @red-0ne and @bryanchriswhite for more context: notion.so/buildwithgrove/Off-chain-Application-Stake-Tracking-6a8bebb107db4f7f9dc62cbe7ba555f7 - expectedBurn := claimSettlementCoin + logger := methodLogger.With("helper", "ensureClaimAmountLimits") + + // TODO_BETA_OR_MAINNET(@red-0ne): The application stake gets reduced with every claim + // settlement. Relay miners use the appStake at the beginning of a session to determine + // the maximum amount they can claim. We need to somehow access and propagate this + // value (via context?) so it is the same for all TLM processors for each claim. + // Note that this will also need to incorporate MintPerClaimGlobalInflation because + // applications are being overcharged by that amount in the meantime. Whatever the + // solution and implementation ends up being, make sure to KISS. + appStake := application.GetStake() + + // Determine the max claimable amount for the supplier based on the application's stake + // in this session. + maxClaimableCoin := sdk.NewCoin(volatile.DenomuPOKT, appStake.Amount.Quo(math.NewInt(sessionkeeper.NumSupplierPerSession))) + + if maxClaimableCoin.Amount.GTE(claimSettlementCoin.Amount) { + logger.Info(fmt.Sprintf("Claim by supplier %s IS WITHIN LIMITS of servicing application %s. Max claimable amount < Claim amount: %v < %v", + supplier.OperatorAddress, application.Address, maxClaimableCoin, claimSettlementCoin.Amount)) + return claimSettlementCoin, nil + } + logger.Warn(fmt.Sprintf("Claim by supplier %s EXCEEDS LIMITS for application %s. Max claimable amount < Claim amount: %v < %v", + supplier.OperatorAddress, application.Address, maxClaimableCoin, claimSettlementCoin.Amount)) + + // Reduce the settlement amount if the application was over-serviced + actualSettlementCoins = maxClaimableCoin + + // Prepare and emit the event for the application being overserviced applicationOverservicedEvent := &tokenomicstypes.EventApplicationOverserviced{ ApplicationAddr: application.Address, - ExpectedBurn: &expectedBurn, - EffectiveBurn: application.GetStake(), + SupplierAddr: supplier.OperatorAddress, + ExpectedBurn: &claimSettlementCoin, + EffectiveBurn: &maxClaimableCoin, } eventManager := cosmostypes.UnwrapSDKContext(ctx).EventManager() if err := eventManager.EmitTypedEvent(applicationOverservicedEvent); err != nil { return cosmostypes.Coin{}, - tokenomicstypes.ErrTokenomicsApplicationOverservicedEvent.Wrapf( - "application address: %s; expected burn %s; effective burn: %s", - application.GetAddress(), - expectedBurn.String(), - application.GetStake().String(), - ) + tokenomicstypes.ErrTokenomicsEmittingEventFailed.Wrapf("error emitting event %v", applicationOverservicedEvent) } - // TODO(@red-0ne) - - return *application.Stake, nil + return actualSettlementCoins, nil } // numRelaysToCoin calculates the amount of uPOKT to mint based on the number of compute units. @@ -626,14 +609,14 @@ func (k Keeper) distributeSupplierRewardsToShareHolders( return nil } -// calculateGlobalMintAllocationFromSettlementAmount calculates the amount of uPOKT -// to mint based on the global inflation rate as a function of the settlement amount -// for a particular claim(s) or session(s). -func calculateGlobalMintAllocationFromSettlementAmount(settlementCoin sdk.Coin) (sdk.Coins, *big.Float) { - // Determine how much new uPOKT to mint based on global inflation +// calculateGlobalPerClaimMintInflationFromSettlementAmount calculates the amount +// of uPOKT to mint based on the global per claim inflation rate as a function of +// the settlement amount for a particular claim(s) or session(s). +func calculateGlobalPerClaimMintInflationFromSettlementAmount(settlementCoin sdk.Coin) (sdk.Coins, *big.Float) { + // Determine how much new uPOKT to mint based on global per claim inflation. // TODO_MAINNET: Consider using fixed point arithmetic for deterministic results. settlementAmtFloat := new(big.Float).SetUint64(settlementCoin.Amount.Uint64()) - newMintAmtFloat := new(big.Float).Mul(settlementAmtFloat, big.NewFloat(MintGlobalInflation)) + newMintAmtFloat := new(big.Float).Mul(settlementAmtFloat, big.NewFloat(MintPerClaimGlobalInflation)) newMintAmtInt, _ := newMintAmtFloat.Int64() mintAmtCoins := sdk.NewCoins(cosmostypes.NewCoin(volatile.DenomuPOKT, math.NewInt(newMintAmtInt))) return mintAmtCoins, newMintAmtFloat diff --git a/x/tokenomics/keeper/token_logic_modules_test.go b/x/tokenomics/keeper/token_logic_modules_test.go index eb2bea113..50fecad21 100644 --- a/x/tokenomics/keeper/token_logic_modules_test.go +++ b/x/tokenomics/keeper/token_logic_modules_test.go @@ -33,6 +33,9 @@ func init() { cmd.InitSDKConfig() } +// TODO_IN_THIS_PR: Tests to add or list +// claimSettlementAmount > maxClaimableAmount + func TestProcessTokenLogicModules_HandleAppGoingIntoDebt(t *testing.T) { keepers, ctx := testkeeper.NewTokenomicsModuleKeepers(t, nil) diff --git a/x/tokenomics/keeper/update_relay_mining_difficulty.go b/x/tokenomics/keeper/update_relay_mining_difficulty.go index 71f2b50fc..d563db86b 100644 --- a/x/tokenomics/keeper/update_relay_mining_difficulty.go +++ b/x/tokenomics/keeper/update_relay_mining_difficulty.go @@ -7,11 +7,13 @@ import ( "fmt" "math/big" + "cosmossdk.io/log" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/pokt-network/poktroll/pkg/crypto/protocol" prooftypes "github.com/pokt-network/poktroll/x/proof/types" "github.com/pokt-network/poktroll/x/tokenomics/types" + tokenomicstypes "github.com/pokt-network/poktroll/x/tokenomics/types" ) // TargetNumRelays is the target number of relays we want the network to mine for @@ -49,17 +51,7 @@ func (k Keeper) UpdateRelayMiningDifficulty( for serviceId, numRelays := range relaysPerServiceMap { prevDifficulty, found := k.GetRelayMiningDifficulty(ctx, serviceId) if !found { - logger.Warn(types.ErrTokenomicsMissingRelayMiningDifficulty.Wrapf( - "No previous relay mining difficulty found for service %s. Initializing with default difficulty %v", - serviceId, prevDifficulty.TargetHash, - ).Error()) - // If a previous difficulty for the service is not found, we initialize a default. - prevDifficulty = types.RelayMiningDifficulty{ - ServiceId: serviceId, - BlockHeight: sdkCtx.BlockHeight(), - NumRelaysEma: numRelays, - TargetHash: prooftypes.DefaultRelayDifficultyTargetHash, - } + prevDifficulty = newDefaultRelayMiningDifficulty(ctx, logger, serviceId, numRelays) } // TODO_MAINNET(@Olshansk): We could potentially compute the smoothing factor @@ -190,3 +182,24 @@ func computeEma(alpha *big.Float, prevEma, currValue uint64) uint64 { newEma, _ := new(big.Float).Add(weightedCurrentContribution, weightedPreviousContribution).Uint64() return newEma } + +func newDefaultRelayMiningDifficulty( + ctx context.Context, + methodLogger log.Logger, + serviceId string, + numRelays uint64, +) tokenomicstypes.RelayMiningDifficulty { + logger := methodLogger.With("helper", "newDefaultRelayMiningDifficulty") + logger.Warn(types.ErrTokenomicsMissingRelayMiningDifficulty.Wrapf( + "No previous relay mining difficulty found for service %s. Creating a temporary relay mining difficulty with %d relays and default target hash %x", + serviceId, numRelays, + ).Error()) + + return tokenomicstypes.RelayMiningDifficulty{ + ServiceId: serviceId, + BlockHeight: sdk.UnwrapSDKContext(ctx).BlockHeight(), + NumRelaysEma: numRelays, + TargetHash: prooftypes.DefaultRelayDifficultyTargetHash, + } + +} diff --git a/x/tokenomics/types/errors.go b/x/tokenomics/types/errors.go index 91b2d761e..24a16cd1b 100644 --- a/x/tokenomics/types/errors.go +++ b/x/tokenomics/types/errors.go @@ -25,7 +25,7 @@ var ( ErrTokenomicsUnmarshalInvalid = sdkerrors.Register(ModuleName, 1116, "failed to unmarshal the provided bytes") ErrTokenomicsDuplicateIndex = sdkerrors.Register(ModuleName, 1117, "cannot have a duplicate index") ErrTokenomicsMissingRelayMiningDifficulty = sdkerrors.Register(ModuleName, 1118, "missing relay mining difficulty") - ErrTokenomicsApplicationOverservicedEvent = sdkerrors.Register(ModuleName, 1119, "application overserviced event cannot be sent") + ErrTokenomicsEmittingEventFailed = sdkerrors.Register(ModuleName, 1119, "failed to emit event") ErrTokenomicsServiceNotFound = sdkerrors.Register(ModuleName, 1120, "service not found") ErrTokenomicsModuleMintFailed = sdkerrors.Register(ModuleName, 1121, "failed to mint uPOKT to tokenomics module account") ErrTokenomicsSendingMintRewards = sdkerrors.Register(ModuleName, 1122, "failed to send minted rewards") diff --git a/x/tokenomics/types/event.pb.go b/x/tokenomics/types/event.pb.go index 1585b4fcf..795d595a9 100644 --- a/x/tokenomics/types/event.pb.go +++ b/x/tokenomics/types/event.pb.go @@ -273,12 +273,20 @@ func (m *EventRelayMiningDifficultyUpdated) GetNewNumRelaysEma() uint64 { return 0 } -// EventApplicationOverserviced is emitted when an application has less stake -// than the expected burn. +// EventApplicationOverserviced is emitted when an application has less stake than +// what a supplier is claiming (i.e. burn is not high enough). type EventApplicationOverserviced struct { - ApplicationAddr string `protobuf:"bytes,1,opt,name=application_addr,json=applicationAddr,proto3" json:"application_addr,omitempty"` - ExpectedBurn *types1.Coin `protobuf:"bytes,2,opt,name=expected_burn,json=expectedBurn,proto3" json:"expected_burn,omitempty"` - EffectiveBurn *types1.Coin `protobuf:"bytes,3,opt,name=effective_burn,json=effectiveBurn,proto3" json:"effective_burn,omitempty"` + ApplicationAddr string `protobuf:"bytes,1,opt,name=application_addr,json=applicationAddr,proto3" json:"application_addr,omitempty"` + SupplierAddr string `protobuf:"bytes,2,opt,name=supplier_addr,json=supplierAddr,proto3" json:"supplier_addr,omitempty"` + // Expected burn is the amount the supplier is claiming for work done + // to service the application during the session. + // This is usually the amount in the Claim object. + ExpectedBurn *types1.Coin `protobuf:"bytes,3,opt,name=expected_burn,json=expectedBurn,proto3" json:"expected_burn,omitempty"` + // Effective burn is the amount that is actually being paid to the supplier + // for the work done. It is less than the expected burn (claim amount) and + // most likely equal to the application's stake divided by the number of suppliers + // in a session. + EffectiveBurn *types1.Coin `protobuf:"bytes,4,opt,name=effective_burn,json=effectiveBurn,proto3" json:"effective_burn,omitempty"` } func (m *EventApplicationOverserviced) Reset() { *m = EventApplicationOverserviced{} } @@ -321,6 +329,13 @@ func (m *EventApplicationOverserviced) GetApplicationAddr() string { return "" } +func (m *EventApplicationOverserviced) GetSupplierAddr() string { + if m != nil { + return m.SupplierAddr + } + return "" +} + func (m *EventApplicationOverserviced) GetExpectedBurn() *types1.Coin { if m != nil { return m.ExpectedBurn @@ -417,56 +432,57 @@ func init() { func init() { proto.RegisterFile("poktroll/tokenomics/event.proto", fileDescriptor_a78874bbf91a58c7) } var fileDescriptor_a78874bbf91a58c7 = []byte{ - // 776 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x55, 0xcd, 0x4e, 0xeb, 0x46, - 0x14, 0x8e, 0xc3, 0x8f, 0x94, 0xa1, 0x40, 0x32, 0x14, 0x35, 0xa5, 0x90, 0x84, 0xa8, 0xaa, 0x28, - 0x15, 0xb6, 0x00, 0xa9, 0xab, 0x0a, 0x35, 0x09, 0xa6, 0x58, 0x2a, 0x49, 0xe4, 0x40, 0x55, 0x75, - 0xe3, 0x3a, 0xf6, 0x49, 0x32, 0x25, 0x9e, 0x31, 0xe3, 0x71, 0x12, 0xde, 0xa2, 0x0f, 0xd0, 0x17, - 0xe8, 0xa2, 0x2f, 0xd1, 0x55, 0xa5, 0x6e, 0x58, 0x76, 0x85, 0x2a, 0xd8, 0xf1, 0x14, 0x57, 0x1e, - 0x3b, 0x3f, 0x04, 0xee, 0xbd, 0xba, 0xcb, 0xbb, 0x49, 0x46, 0xe7, 0x7c, 0xdf, 0x37, 0xe7, 0x7c, - 0x73, 0x72, 0x82, 0x8a, 0x3e, 0xbb, 0x16, 0x9c, 0xf5, 0xfb, 0x9a, 0x60, 0xd7, 0x40, 0x99, 0x47, - 0x9c, 0x40, 0x83, 0x01, 0x50, 0xa1, 0xfa, 0x9c, 0x09, 0x86, 0x37, 0xc6, 0x00, 0x75, 0x0a, 0xd8, - 0x2a, 0x38, 0x2c, 0xf0, 0x58, 0xa0, 0xb5, 0xed, 0x00, 0xb4, 0xc1, 0x61, 0x1b, 0x84, 0x7d, 0xa8, - 0x39, 0x8c, 0xd0, 0x98, 0xb4, 0xf5, 0x69, 0x97, 0x75, 0x99, 0x3c, 0x6a, 0xd1, 0x29, 0x89, 0x6e, - 0x4d, 0xee, 0xf2, 0x39, 0x63, 0x1d, 0xcd, 0xe9, 0xdb, 0xc4, 0x4b, 0x72, 0xa5, 0xb9, 0x1c, 0x87, - 0x9b, 0x90, 0x70, 0xf0, 0x26, 0x85, 0x94, 0xff, 0x4a, 0xa3, 0x9c, 0x1e, 0x15, 0x56, 0x8b, 0x68, - 0xfa, 0xc8, 0x27, 0x1c, 0x5c, 0xfc, 0x2d, 0x5a, 0x92, 0x32, 0x79, 0xa5, 0xa4, 0xec, 0xad, 0x1c, - 0x6d, 0xaa, 0x93, 0x72, 0xa5, 0x8e, 0x2a, 0xc1, 0xd5, 0xcc, 0xd3, 0x7d, 0x31, 0xc6, 0x99, 0xf1, - 0x17, 0x3e, 0x40, 0x88, 0x86, 0x9e, 0xc5, 0xa1, 0x6f, 0xdf, 0x06, 0xf9, 0x74, 0x49, 0xd9, 0x5b, - 0xac, 0xae, 0x3d, 0xdd, 0x17, 0x67, 0xa2, 0x66, 0x86, 0x86, 0x9e, 0x29, 0x8f, 0xb8, 0x82, 0x72, - 0x51, 0xc2, 0x61, 0x9e, 0x1f, 0x0a, 0xb0, 0x42, 0x4a, 0x44, 0x90, 0x5f, 0x90, 0xac, 0xcd, 0xa7, - 0xfb, 0xe2, 0xcb, 0xa4, 0xb9, 0x4e, 0x43, 0xaf, 0x16, 0x47, 0xae, 0xa2, 0x00, 0xa6, 0x28, 0x07, - 0x51, 0xd1, 0xb6, 0x20, 0x8c, 0x5a, 0x1c, 0xec, 0x80, 0xd1, 0xfc, 0x62, 0x49, 0xd9, 0x5b, 0x3b, - 0xda, 0x57, 0x5f, 0x31, 0x59, 0x9d, 0xf6, 0x29, 0x29, 0xa6, 0x64, 0xc4, 0xd7, 0xbd, 0x10, 0x32, - 0xb3, 0x30, 0x07, 0x2c, 0xff, 0xf9, 0xcc, 0xaf, 0x16, 0x08, 0xd1, 0xff, 0xa8, 0xfc, 0xfa, 0x0d, - 0xe5, 0x64, 0x49, 0xd6, 0xcc, 0x28, 0x24, 0x7e, 0x7d, 0x35, 0x5f, 0x75, 0x33, 0xfa, 0x34, 0xa7, - 0xb8, 0x59, 0xaf, 0x5e, 0x88, 0x98, 0x59, 0x7f, 0x0e, 0x5e, 0xfe, 0x23, 0x8d, 0x76, 0xa5, 0x57, - 0xb2, 0xfc, 0x0b, 0x42, 0x09, 0xed, 0x9e, 0x92, 0x4e, 0x87, 0x38, 0x61, 0x5f, 0xdc, 0x5e, 0xf9, - 0xae, 0x2d, 0xc0, 0xc5, 0x3b, 0x08, 0x05, 0xc0, 0x07, 0xc4, 0x01, 0x8b, 0xb8, 0xd2, 0xc0, 0x8c, - 0x99, 0x49, 0x22, 0x86, 0x8b, 0x4f, 0xd0, 0xb6, 0xcf, 0x61, 0x60, 0x09, 0x9b, 0x77, 0x41, 0x58, - 0x3d, 0x3b, 0xe8, 0x59, 0x3d, 0x18, 0x59, 0x40, 0x1d, 0xe6, 0x82, 0x2b, 0x4d, 0xcb, 0x98, 0xf9, - 0x08, 0x73, 0x29, 0x21, 0xe7, 0x76, 0xd0, 0x3b, 0x87, 0x91, 0x1e, 0xe7, 0xf1, 0x77, 0xe8, 0x0b, - 0x0a, 0xc3, 0xb7, 0xd2, 0x17, 0x24, 0xfd, 0x33, 0x0a, 0xc3, 0x57, 0xd9, 0x07, 0x68, 0x43, 0xde, - 0x3e, 0x7d, 0x0f, 0x0b, 0x3c, 0x5b, 0x1a, 0xb6, 0x18, 0x75, 0x0c, 0x83, 0xfa, 0xf8, 0x75, 0x74, - 0xcf, 0xc6, 0xdf, 0x20, 0x1c, 0x5d, 0x36, 0x87, 0x5e, 0x92, 0xe8, 0x75, 0x0a, 0xc3, 0x59, 0x70, - 0xf9, 0x5f, 0x05, 0x6d, 0x4b, 0x7b, 0x2a, 0xbe, 0xdf, 0x27, 0x8e, 0x9c, 0xb2, 0xc6, 0x00, 0x78, - 0xd2, 0xbb, 0x8b, 0xbf, 0x46, 0x59, 0x7b, 0x9a, 0xb2, 0x6c, 0xd7, 0xe5, 0x89, 0x3f, 0xeb, 0x33, - 0xf1, 0x8a, 0xeb, 0x72, 0x7c, 0x82, 0x56, 0x61, 0xe4, 0x83, 0x23, 0xc0, 0xb5, 0xda, 0x21, 0xa7, - 0xd2, 0x96, 0x95, 0xa3, 0xcf, 0xd5, 0x78, 0xa5, 0xa8, 0xd1, 0x4a, 0x51, 0x93, 0x95, 0xa2, 0xd6, - 0x18, 0xa1, 0xe6, 0x27, 0x63, 0x7c, 0x35, 0xe4, 0x14, 0x7f, 0x8f, 0xd6, 0xa0, 0xd3, 0x01, 0x47, - 0x90, 0x01, 0xc4, 0x02, 0x0b, 0xef, 0x13, 0x58, 0x9d, 0x10, 0x22, 0x85, 0xf2, 0xdf, 0x0a, 0xfa, - 0x72, 0xbe, 0x1b, 0x13, 0x88, 0xd7, 0x0e, 0x79, 0x90, 0x4c, 0xcf, 0x4d, 0x08, 0x81, 0xf8, 0x90, - 0xae, 0x9e, 0x8f, 0x46, 0x7a, 0x7e, 0x34, 0x64, 0x3a, 0x08, 0x22, 0x15, 0x32, 0x7e, 0xc9, 0x4c, - 0x12, 0x31, 0x5c, 0x7c, 0x88, 0x96, 0x6d, 0x8f, 0x85, 0xc9, 0x7c, 0xbf, 0xb3, 0x97, 0x04, 0xb8, - 0xff, 0x2b, 0xda, 0x7c, 0x75, 0x3f, 0xe0, 0x5d, 0xb4, 0xa3, 0xff, 0xdc, 0x34, 0xcc, 0xca, 0xa5, - 0xd1, 0xa8, 0x5b, 0xa6, 0x5e, 0x69, 0x35, 0xea, 0xd6, 0x55, 0xbd, 0xd5, 0xd4, 0x6b, 0xc6, 0x99, - 0xa1, 0x9f, 0x66, 0x53, 0x38, 0x87, 0x56, 0x9b, 0x66, 0xa3, 0x71, 0x66, 0x5d, 0x18, 0xad, 0x96, - 0x51, 0xff, 0x21, 0xab, 0x4c, 0x43, 0x46, 0xfd, 0xa7, 0xca, 0x8f, 0xc6, 0x69, 0x36, 0x5d, 0xbd, - 0xf8, 0xe7, 0xa1, 0xa0, 0xdc, 0x3d, 0x14, 0x94, 0xff, 0x1f, 0x0a, 0xca, 0xef, 0x8f, 0x85, 0xd4, - 0xdd, 0x63, 0x21, 0xf5, 0xdf, 0x63, 0x21, 0xf5, 0xcb, 0x71, 0x97, 0x88, 0x5e, 0xd8, 0x56, 0x1d, - 0xe6, 0x69, 0xd1, 0x0f, 0xf1, 0x80, 0x82, 0x18, 0x32, 0x7e, 0xad, 0x4d, 0x76, 0xf8, 0x68, 0xf6, - 0xdf, 0x44, 0xdc, 0xfa, 0x10, 0xb4, 0x97, 0xe5, 0x16, 0x3f, 0x7e, 0x13, 0x00, 0x00, 0xff, 0xff, - 0xe7, 0x04, 0xe0, 0xc6, 0x71, 0x06, 0x00, 0x00, + // 793 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x55, 0x4f, 0x6f, 0xe3, 0x44, + 0x14, 0x8f, 0xb3, 0xd9, 0x95, 0x32, 0xbb, 0x69, 0x93, 0x59, 0x2a, 0x42, 0xd9, 0x4d, 0xb2, 0x01, + 0xa1, 0xb2, 0xa8, 0xb6, 0xda, 0x95, 0x38, 0xa1, 0x8a, 0x24, 0x75, 0xa9, 0x25, 0x9a, 0x44, 0x4e, + 0x8b, 0x10, 0x17, 0xe3, 0xd8, 0x2f, 0xc9, 0xd0, 0x78, 0xc6, 0x9d, 0x19, 0x27, 0xe9, 0xb7, 0xe0, + 0x03, 0xf0, 0x05, 0x38, 0xf0, 0x25, 0x38, 0x71, 0xec, 0x91, 0x53, 0x85, 0xda, 0x5b, 0x4f, 0x7c, + 0x04, 0xe4, 0xb1, 0xf3, 0xa7, 0x69, 0x01, 0x71, 0xe4, 0xd2, 0x8e, 0x7e, 0xef, 0xf7, 0x7b, 0xf3, + 0xde, 0x6f, 0x9e, 0x5f, 0x50, 0x35, 0x64, 0xe7, 0x92, 0xb3, 0xf1, 0xd8, 0x90, 0xec, 0x1c, 0x28, + 0x0b, 0x88, 0x27, 0x0c, 0x98, 0x00, 0x95, 0x7a, 0xc8, 0x99, 0x64, 0xf8, 0xe5, 0x9c, 0xa0, 0x2f, + 0x09, 0xdb, 0x15, 0x8f, 0x89, 0x80, 0x09, 0xa3, 0xef, 0x0a, 0x30, 0x26, 0x7b, 0x7d, 0x90, 0xee, + 0x9e, 0xe1, 0x31, 0x42, 0x13, 0xd1, 0xf6, 0x7b, 0x43, 0x36, 0x64, 0xea, 0x68, 0xc4, 0xa7, 0x14, + 0xdd, 0x5e, 0xdc, 0x15, 0x72, 0xc6, 0x06, 0x86, 0x37, 0x76, 0x49, 0x90, 0xc6, 0x6a, 0x6b, 0x31, + 0x0e, 0x17, 0x11, 0xe1, 0x10, 0x2c, 0x0a, 0xa9, 0xff, 0x92, 0x45, 0x25, 0x33, 0x2e, 0xac, 0x15, + 0xcb, 0xcc, 0x59, 0x48, 0x38, 0xf8, 0xf8, 0x73, 0xf4, 0x54, 0xa5, 0x29, 0x6b, 0x35, 0x6d, 0xe7, + 0xf9, 0xfe, 0x96, 0xbe, 0x28, 0x57, 0xe5, 0xd1, 0x15, 0xb9, 0x99, 0xbf, 0xbb, 0xae, 0x26, 0x3c, + 0x3b, 0xf9, 0x87, 0x77, 0x11, 0xa2, 0x51, 0xe0, 0x70, 0x18, 0xbb, 0x97, 0xa2, 0x9c, 0xad, 0x69, + 0x3b, 0xb9, 0xe6, 0xc6, 0xdd, 0x75, 0x75, 0x05, 0xb5, 0xf3, 0x34, 0x0a, 0x6c, 0x75, 0xc4, 0x0d, + 0x54, 0x8a, 0x03, 0x1e, 0x0b, 0xc2, 0x48, 0x82, 0x13, 0x51, 0x22, 0x45, 0xf9, 0x89, 0x52, 0x6d, + 0xdd, 0x5d, 0x57, 0x1f, 0x06, 0xed, 0x4d, 0x1a, 0x05, 0xad, 0x04, 0x39, 0x8b, 0x01, 0x4c, 0x51, + 0x09, 0xe2, 0xa2, 0x5d, 0x49, 0x18, 0x75, 0x38, 0xb8, 0x82, 0xd1, 0x72, 0xae, 0xa6, 0xed, 0x6c, + 0xec, 0xbf, 0xd5, 0x1f, 0x31, 0x59, 0x5f, 0xf6, 0xa9, 0x24, 0xb6, 0x52, 0x24, 0xd7, 0x3d, 0x48, + 0x64, 0x17, 0x61, 0x8d, 0x58, 0xff, 0xf9, 0x9e, 0x5f, 0x3d, 0x90, 0x72, 0xfc, 0xbf, 0xf2, 0xeb, + 0x07, 0x54, 0x52, 0x25, 0x39, 0x2b, 0xa3, 0x90, 0xfa, 0xf5, 0xc9, 0x7a, 0xd5, 0xdd, 0xf8, 0xaf, + 0xbd, 0xe4, 0xad, 0x7a, 0xf5, 0x20, 0x89, 0x5d, 0x0c, 0xd7, 0xe8, 0xf5, 0x9f, 0xb2, 0xe8, 0x8d, + 0xf2, 0x4a, 0x95, 0x7f, 0x42, 0x28, 0xa1, 0xc3, 0x43, 0x32, 0x18, 0x10, 0x2f, 0x1a, 0xcb, 0xcb, + 0xb3, 0xd0, 0x77, 0x25, 0xf8, 0xf8, 0x35, 0x42, 0x02, 0xf8, 0x84, 0x78, 0xe0, 0x10, 0x5f, 0x19, + 0x98, 0xb7, 0xf3, 0x29, 0x62, 0xf9, 0xf8, 0x00, 0xbd, 0x0a, 0x39, 0x4c, 0x1c, 0xe9, 0xf2, 0x21, + 0x48, 0x67, 0xe4, 0x8a, 0x91, 0x33, 0x82, 0x99, 0x03, 0xd4, 0x63, 0x3e, 0xf8, 0xca, 0xb4, 0xbc, + 0x5d, 0x8e, 0x39, 0xa7, 0x8a, 0x72, 0xec, 0x8a, 0xd1, 0x31, 0xcc, 0xcc, 0x24, 0x8e, 0xbf, 0x40, + 0x1f, 0x52, 0x98, 0xfe, 0xad, 0xfc, 0x89, 0x92, 0xbf, 0x4f, 0x61, 0xfa, 0xa8, 0x7a, 0x17, 0xbd, + 0x54, 0xb7, 0x2f, 0xdf, 0xc3, 0x81, 0xc0, 0x55, 0x86, 0xe5, 0xe2, 0x8e, 0x61, 0xd2, 0x9e, 0xbf, + 0x8e, 0x19, 0xb8, 0xf8, 0x33, 0x84, 0xe3, 0xcb, 0xd6, 0xd8, 0x4f, 0x15, 0x7b, 0x93, 0xc2, 0x74, + 0x95, 0x5c, 0xff, 0x53, 0x43, 0xaf, 0x94, 0x3d, 0x8d, 0x30, 0x1c, 0x13, 0x4f, 0x4d, 0x59, 0x67, + 0x02, 0x3c, 0xed, 0xdd, 0xc7, 0x9f, 0xa2, 0xa2, 0xbb, 0x0c, 0x39, 0xae, 0xef, 0xf3, 0xd4, 0x9f, + 0xcd, 0x15, 0xbc, 0xe1, 0xfb, 0x1c, 0x7f, 0x84, 0x0a, 0x22, 0x8a, 0x31, 0xe0, 0x09, 0x2f, 0xb1, + 0xe5, 0xc5, 0x1c, 0x54, 0xa4, 0x03, 0x54, 0x80, 0x59, 0x08, 0x9e, 0x04, 0xdf, 0xe9, 0x47, 0x9c, + 0xaa, 0xe6, 0x9f, 0xef, 0x7f, 0xa0, 0x27, 0x7b, 0x47, 0x8f, 0xf7, 0x8e, 0x9e, 0xee, 0x1d, 0xbd, + 0xc5, 0x08, 0xb5, 0x5f, 0xcc, 0xf9, 0xcd, 0x88, 0x53, 0xfc, 0x25, 0xda, 0x80, 0xc1, 0x00, 0x3c, + 0x49, 0x26, 0x90, 0x24, 0xc8, 0xfd, 0x5b, 0x82, 0xc2, 0x42, 0x10, 0x67, 0xa8, 0xff, 0xaa, 0xa1, + 0x8f, 0xd7, 0x5b, 0xb6, 0x81, 0x04, 0xfd, 0x88, 0x8b, 0x74, 0xc4, 0x2e, 0x22, 0x10, 0xf2, 0xbf, + 0xb4, 0x7e, 0x7f, 0x7e, 0xb2, 0xeb, 0xf3, 0xa3, 0xc2, 0x42, 0xc4, 0x59, 0xc8, 0xfc, 0xb9, 0xf3, + 0x29, 0x62, 0xf9, 0x78, 0x0f, 0x3d, 0x73, 0x03, 0x16, 0xa5, 0x1f, 0xc1, 0x3f, 0xf6, 0x92, 0x12, + 0xdf, 0x7e, 0x8f, 0xb6, 0x1e, 0x5d, 0x22, 0xf8, 0x0d, 0x7a, 0x6d, 0x7e, 0xdb, 0xb5, 0xec, 0xc6, + 0xa9, 0xd5, 0x69, 0x3b, 0xb6, 0xd9, 0xe8, 0x75, 0xda, 0xce, 0x59, 0xbb, 0xd7, 0x35, 0x5b, 0xd6, + 0x91, 0x65, 0x1e, 0x16, 0x33, 0xb8, 0x84, 0x0a, 0x5d, 0xbb, 0xd3, 0x39, 0x72, 0x4e, 0xac, 0x5e, + 0xcf, 0x6a, 0x7f, 0x55, 0xd4, 0x96, 0x90, 0xd5, 0xfe, 0xa6, 0xf1, 0xb5, 0x75, 0x58, 0xcc, 0x36, + 0x4f, 0x7e, 0xbb, 0xa9, 0x68, 0x57, 0x37, 0x15, 0xed, 0x8f, 0x9b, 0x8a, 0xf6, 0xe3, 0x6d, 0x25, + 0x73, 0x75, 0x5b, 0xc9, 0xfc, 0x7e, 0x5b, 0xc9, 0x7c, 0xf7, 0x6e, 0x48, 0xe4, 0x28, 0xea, 0xeb, + 0x1e, 0x0b, 0x8c, 0xf8, 0x6b, 0xdd, 0xa5, 0x20, 0xa7, 0x8c, 0x9f, 0x1b, 0x8b, 0x45, 0x3f, 0x5b, + 0xfd, 0xc9, 0x91, 0x97, 0x21, 0x88, 0xfe, 0x33, 0xb5, 0xea, 0xdf, 0xfd, 0x15, 0x00, 0x00, 0xff, + 0xff, 0x37, 0x47, 0xc1, 0x88, 0x96, 0x06, 0x00, 0x00, } func (m *EventClaimExpired) Marshal() (dAtA []byte, err error) { @@ -653,7 +669,7 @@ func (m *EventApplicationOverserviced) MarshalToSizedBuffer(dAtA []byte) (int, e i = encodeVarintEvent(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x1a + dAtA[i] = 0x22 } if m.ExpectedBurn != nil { { @@ -665,6 +681,13 @@ func (m *EventApplicationOverserviced) MarshalToSizedBuffer(dAtA []byte) (int, e i = encodeVarintEvent(dAtA, i, uint64(size)) } i-- + dAtA[i] = 0x1a + } + if len(m.SupplierAddr) > 0 { + i -= len(m.SupplierAddr) + copy(dAtA[i:], m.SupplierAddr) + i = encodeVarintEvent(dAtA, i, uint64(len(m.SupplierAddr))) + i-- dAtA[i] = 0x12 } if len(m.ApplicationAddr) > 0 { @@ -825,6 +848,10 @@ func (m *EventApplicationOverserviced) Size() (n int) { if l > 0 { n += 1 + l + sovEvent(uint64(l)) } + l = len(m.SupplierAddr) + if l > 0 { + n += 1 + l + sovEvent(uint64(l)) + } if m.ExpectedBurn != nil { l = m.ExpectedBurn.Size() n += 1 + l + sovEvent(uint64(l)) @@ -1399,6 +1426,38 @@ func (m *EventApplicationOverserviced) Unmarshal(dAtA []byte) error { m.ApplicationAddr = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SupplierAddr", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + 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 ErrInvalidLengthEvent + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvent + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SupplierAddr = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field ExpectedBurn", wireType) } @@ -1434,7 +1493,7 @@ func (m *EventApplicationOverserviced) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 3: + case 4: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field EffectiveBurn", wireType) } From 98736f3c81b0126b0b4795007d32bb18133c40c4 Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Wed, 21 Aug 2024 15:11:50 -0400 Subject: [PATCH 04/31] Revert tokenomic docs --- .../protocol/architecture/_category_.json | 4 +- .../docs/protocol/architecture/network.md | 2 +- .../docs/protocol/tokenomics/_category_.json | 8 - .../docs/protocol/tokenomics/resources.md | 21 -- .../tokenomics/token_logic_modules.md | 287 ------------------ .../docs/protocol/upgrades/_category_.json | 2 +- 6 files changed, 4 insertions(+), 320 deletions(-) delete mode 100644 docusaurus/docs/protocol/tokenomics/_category_.json delete mode 100644 docusaurus/docs/protocol/tokenomics/resources.md delete mode 100644 docusaurus/docs/protocol/tokenomics/token_logic_modules.md diff --git a/docusaurus/docs/protocol/architecture/_category_.json b/docusaurus/docs/protocol/architecture/_category_.json index 985d17b7b..c4be422a5 100644 --- a/docusaurus/docs/protocol/architecture/_category_.json +++ b/docusaurus/docs/protocol/architecture/_category_.json @@ -1,6 +1,6 @@ { - "label": "[Outdated] Architecture", - "position": 6, + "label": "Architecture", + "position": 7, "link": { "type": "generated-index", "description": "Documentation related to the high-level design, flows and components of the poktroll repo." diff --git a/docusaurus/docs/protocol/architecture/network.md b/docusaurus/docs/protocol/architecture/network.md index b7949986e..d0e25f1d3 100644 --- a/docusaurus/docs/protocol/architecture/network.md +++ b/docusaurus/docs/protocol/architecture/network.md @@ -1,5 +1,5 @@ --- -title: Outdated - Pocket Actors, Nodes & Data Availability Network +title: Pocket Actors, Nodes & Data Availability Network sidebar_position: 1 --- diff --git a/docusaurus/docs/protocol/tokenomics/_category_.json b/docusaurus/docs/protocol/tokenomics/_category_.json deleted file mode 100644 index c23caaa17..000000000 --- a/docusaurus/docs/protocol/tokenomics/_category_.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "label": "Tokenomics", - "position": 5, - "link": { - "type": "generated-index", - "description": "Documentation related to Pocket Network tokenomics." - } -} diff --git a/docusaurus/docs/protocol/tokenomics/resources.md b/docusaurus/docs/protocol/tokenomics/resources.md deleted file mode 100644 index b652b0349..000000000 --- a/docusaurus/docs/protocol/tokenomics/resources.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: Tokenomics Resources -sidebar_position: 1 ---- - -# Tokenomics Resources - -:::warning - -This is an active an ever evolving work. We are working on a single source of truth. - -::: - -The following resources serve as the foundation for the Shannon Upgrade Tokenomics. - -- [Token Logic Module](https://docs.pokt.network/pokt-protocol/the-shannon-upgrade/proposed-tokenomics/token-logic-modules) design approach. -- [Shannon Tokenomics Static](https://github.com/pokt-network/shannon-tokenomics-static-tests) modeling & evaluation -- [Relay Mining](https://arxiv.org/abs/2305.10672) paper -- [Probabilistic Proofs](https://github.com/pokt-network/pocket-core/blob/staging/docs/proposals/probabilistic_proofs.md) design - -Thank you to [@Rama_stdout](https://x.com/Rama_stdout), [@shane8burger](https://x.com/shane8burger) and [@olshansky](https://x.com/olshansky) for the contributions! diff --git a/docusaurus/docs/protocol/tokenomics/token_logic_modules.md b/docusaurus/docs/protocol/tokenomics/token_logic_modules.md deleted file mode 100644 index fd70d0fe9..000000000 --- a/docusaurus/docs/protocol/tokenomics/token_logic_modules.md +++ /dev/null @@ -1,287 +0,0 @@ ---- -title: Token Logic Modules -sidebar_position: 2 ---- - -# Token Logic Modules - -- [Introduction](#introduction) -- [Background: Max Claimable Amount](#background-max-claimable-amount) -- [TLM (pre) Processing](#tlm-pre-processing) -- [TLM: Mint=Burn (MEB)](#tlm-mintburn-meb) -- [TLM: Global Mint (GM)](#tlm-global-mint-gm) -- [TLM: Global Mint Reimbursement Request (GMRR)](#tlm-global-mint-reimbursement-request-gmrr) - -## Introduction - -:::warning - -Note that this is an active WIP and the [resources here](./resources.md) are the best starting references to learn more. - -::: - -Token Logic Modules (TLMs) processing involves: - -1. `TLM pre-processing` - A general pre-processor determining the amount of tokens to settle per claim. -2. `TLM processing` - Iteration through all of the TLMs one by one. -3. `TLM processor` - Individual processing each TLM independent of one another. - -## Background: Max Claimable Amount - -_tl;dr Max Claimable Amount ∝ (Application Stake / Number of Suppliers per Session)_ - -Per **Algorithm 1** of the [Relay Mining paper](https://arxiv.org/pdf/2305.10672), -the maximum amount a supplier can claim from an application in a single session is -proportional to the Application's stake divided by the number of suppliers in the session. - -This is referred to as "Relay Mining Payable Relay Accumulation" in the paper and -can be seen in the following image: - -![Algorithm 1](https://github.com/user-attachments/assets/d1a61535-aa31-447d-88ea-c8d14dcb20c6) - -## TLM (pre) Processing - -_tl;dr Determine if the claim settlement amount is greater than the maximum claimable amount and then run each individual TLM._ - -**Prior to** processing each individual TLM, we need to understand if the amount claimed -by the supplier adheres to the optimistic maxima set per the limits of Relay Mining. - -Suppliers always have the option to over-service an application (**i.e. do free work**), -in exchange for providing a good service to the network. This may lead to offchain -reputation benefits (e.g. Gateways favoring them), but their on-chain rewards -are still limited as a function of the application's stake before the session started -and the number of suppliers in the session. - -:::note - -TODO_POST_MAINNET: After the Shannon upgrade, the team at Grove has a lot of ideas -related to on-chain reputation, [supplier gossiping](https://www.notion.so/buildwithgrove/Off-chain-Application-Stake-Tracking-6a8bebb107db4f7f9dc62cbe7ba555f7?pvs=4), and -much more, but that is out of scope for the initial implementation. - -::: - -```mermaid ---- -title: "Token Logic Modules (pre) Processing" ---- -flowchart TB - CSA(["Claim Settlement Amount (CSA)"]) - MCA(["MaxClaimPerSupplier (MCA)
= (AppStake / NumSuppliersPerSession)"]) - CC{"Is CSA > MCA?"} - Update(Set SA = MCA
Broadcast Event) - SOAE{{Application Overserviced
Event}} - TLMP[["TLM Processor (SA)"]] - - CSA -- CSA --> CC - MCA -- MCA --> CC - - Update -..-> SOAE - CC -- Yes --> Update - CC -- No
SA=CSA --> TLMP - Update -- SA=CSA --> TLMP - - TLMP --SA--> TLMBEM[[TLM: Burn Equals Mint]] - TLMP --SA--> TLMGI[[TLM: Global Inflation]] - TLMP --SA--> TLMGIRR[[TLM: Global Inflation Reimbursement Request]] - - classDef tlm fill:#54ebd5,stroke:#333,stroke-width:2px; - classDef question fill:#e3db6d,stroke:#333,stroke-width:2px; - classDef event fill:#e8b761,stroke:#333,stroke-width:2px; - - class TLMP,TLMBEM,TLMGI,TLMGIRR tlm; - class SOAE event; - class CC question; -``` - -## TLM: Mint=Burn (MEB) - -_tl;dr The transfer of tokens from the application to the supplier based on the amount of work received and provided respectively.._ - -The `Mint=Burn` TLM is, _theoretically_, the only TLM necessary when the network -reaches equilibrium in the far future. - -The same amount of tokens that is minted in the **supplier module** is burned from -the **application module**. The stake of the application paying for work is reduced -and the rewards are distributed to the supplier and its revenue shareholder addresses. - -```mermaid ---- -title: "Token Logic Module: Mint=Burn" ---- -flowchart TD - SA(["Settlement Amount (SA)"]) - - SA -- Mint SA coins --> SM - SA -- Burn SA coins--> AM - - subgraph SO[Supplier Operations] - SM[[Supplier Module]] - SK[(Supplier Keeper)] - SD{Distribute SA coins} - OPA[Operator Address] - OA[Owner Address] - RSA[Revenue Share Addresses] - - SM -.- SK - SD -->|% Distribution
Increase Balance| OPA - SD -->|% Distribution
Increase Balance| OA - SD -->|% Distribution
Increase Balance| RSA - end - - subgraph AO[Application Operations] - AM[[Application Module]] - AK[(Application Keeper)] - AA[Application Address] - - AM -.- AK - AK -. Reduce Stake by SA .-> AA - AA -.- TODO{See TODO below} - end - - SM --> SD - - classDef module fill:#f9f,stroke:#333,stroke-width:2px; - classDef address fill:#bbf,stroke:#333,stroke-width:2px; - classDef question fill:#e3db6d,stroke:#333,stroke-width:2px; - classDef event fill:#e8b761,stroke:#333,stroke-width:2px; - - class SM,AM module; - class RSA,OA,OPA,AA address; - class TODO question; -``` - -:::note - -TODO_MAINNET: If the application stake has dropped to (near?) zero, should -we unstake it? Should we use it's balance? Should their be a payee of last resort? -Make sure to document whatever decision we come to. - -::: - -## TLM: Global Mint (GM) - -_tl;dr Distributed newly minted coins on a per claim basis to all involved stakeholders._ - -The `Global Mint` TLM is, _theoretically_, going to reach `zero`the only when the network -reaches equilibrium in the far future. - -On a per claim basis, the network mints new tokens based on the the amount of work -claimed. The newly minted tokens are distributed to the supplier, DAO, service owner -and application based on the values of various governance params. - -```mermaid ---- -title: "Token Logic Module: Global Mint" ---- -flowchart TD - SC(["Settlement Coin (SC)"]) - PCI(["Per Claim Global Inflation
(Governance Parameter)"]) - IMC(["Inflation Mint Coin (IMC)"]) - - DA(["DAO Mint Allocation"]) - PA(["Proposer Mint Allocation"]) - SA(["Supplier Mint Allocation"]) - SOA(["Source Owner Mint Allocation"]) - AA(["Application Mint Allocation"]) - - - SC --> IMC - PCI --> IMC - IMC --> TO - - subgraph TO[Tokenomics Operations] - TM[[Tokenomics Module]] - TK[(Tokenomics Keeper)] - TM -..- TK - end - - - DA --> ID - PA --> ID - TO -- New Mint Coin (NMC)--> ID - SA --> ID - AA --> ID - - subgraph ID[Inflation Distribution] - NMC["New Mint Coin (NMC)"] - APPA["Application Address"] - SPPA["Supplier Address"] - DAOA["DAO Address"] - SOA["Service Owner Address"] - PRA["Proposer Address"] - - NMC -->|% Mint Allocation| APPA - NMC -->|% Mint Allocation| SPPA - NMC -->|% Mint Allocation| DAOA - NMC -->|% Mint Allocation| SOA - NMC -->|% Mint Allocation| PRA - end - - classDef module fill:#f9f,stroke:#333,stroke-width:2px; - classDef address fill:#bbf,stroke:#333,stroke-width:2px; - classDef question fill:#e3db6d,stroke:#333,stroke-width:2px; - classDef govparam fill:#d04a36,stroke:#333,stroke-width:2px; - classDef event fill:#e8b761,stroke:#333,stroke-width:2px; - - class TM module; - class PCI,DA,PA,SA,AA govparam; - class APPA,SPPA,DAOA,SOA,PRA address; -``` - -## TLM: Global Mint Reimbursement Request (GMRR) - -_tl;dr Prevent self-dealing by over-charging applications, sending the excess to the DAO/PNF, and emitting an event as a reimbursement request._ - -This TLM **MUST** be processed alongside the Global Mint TLM. - -This TLM can, **theoretically**, be removed if self-dealing attacks are not a concern, -or if the global mint per claim governance parameter is set to zero. - -The goal of the TLM is to overcharge applications equal to the global inflation amount -and send those funds to the DAO/PNF. This forces potentially self-dealing gateways to -"show face" in front of the DAO/PNF and request reimbursement. - -The event emitted creates an easy, onchain mechanism, to track reimbursement handled offchain. - -A side effect of this TLM is creating additional buy pressure of the token as Applications -and Gateways will be responsible for frequently "topping up" their balances and app stakes. - -```mermaid ---- -title: "Token Logic Module: Global Mint Reimbursement Request" ---- -flowchart TD - SC(["Settlement Coin (SC)"]) - PCI(["Per Claim Global Inflation
(Governance Parameter)"]) - IMC(["Inflation Mint Coin (IMC)"]) - ARRE{{Application Reimbursement
Request Event}} - - SC --> IMC - PCI --> IMC - IMC --IMC--> AO - - - subgraph AO[Application Operations] - AM[[Application Module]] - AK[(Application Keeper)] - AA[Application Address] - DA[DAO Address] - - AM -.- AK - AK -. Reduce Stake by IMC .-> AA - AM -..-> |Increase Balance by IMC| DA - end - - AO -. Emit Event.-> ARRE - - classDef module fill:#f9f,stroke:#333,stroke-width:2px; - classDef address fill:#bbf,stroke:#333,stroke-width:2px; - classDef question fill:#e3db6d,stroke:#333,stroke-width:2px; - classDef govparam fill:#d04a36,stroke:#333,stroke-width:2px; - classDef event fill:#e8b761,stroke:#333,stroke-width:2px; - - class AM module; - class ARRE event; - class PCI govparam; - class AA,DA address; -``` diff --git a/docusaurus/docs/protocol/upgrades/_category_.json b/docusaurus/docs/protocol/upgrades/_category_.json index 2e80f4c80..5fe4a715b 100644 --- a/docusaurus/docs/protocol/upgrades/_category_.json +++ b/docusaurus/docs/protocol/upgrades/_category_.json @@ -1,6 +1,6 @@ { "label": "Upgrades", - "position": 4, + "position": 7, "link": { "type": "generated-index", "description": "Documentation related to Pocket Network protocol upgrades." From eeabb30c17d82ad363619fc19231483dd303f006 Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Wed, 21 Aug 2024 15:33:06 -0400 Subject: [PATCH 05/31] Performed self review --- e2e/tests/0_settlement.feature | 3 +++ pkg/relayer/session/sessiontree.go | 1 + x/tokenomics/keeper/token_logic_modules.go | 12 +++++------- x/tokenomics/keeper/token_logic_modules_test.go | 7 +++++-- .../keeper/update_relay_mining_difficulty.go | 6 ++++-- 5 files changed, 18 insertions(+), 11 deletions(-) diff --git a/e2e/tests/0_settlement.feature b/e2e/tests/0_settlement.feature index 358d2cd27..b4eaf2441 100644 --- a/e2e/tests/0_settlement.feature +++ b/e2e/tests/0_settlement.feature @@ -26,6 +26,9 @@ Feature: Tokenomics Namespace Then the account balance of "supplier1" should be "420" uPOKT "more" than before And the "application" stake of "app1" should be "420" uPOKT "less" than before + # TODO_IN_THIS_PR: Add the following test + # Scenario: Supplier overservices an application and gets paid for less work than claimed + # TODO_ADDTEST: Implement the following scenarios # Scenario: Emissions equals burn when a claim is created and a valid proof is submitted but not required # Scenario: No emissions or burn when a claim is created and an invalid proof is submitted diff --git a/pkg/relayer/session/sessiontree.go b/pkg/relayer/session/sessiontree.go index d54992c82..1a45883e1 100644 --- a/pkg/relayer/session/sessiontree.go +++ b/pkg/relayer/session/sessiontree.go @@ -70,6 +70,7 @@ type sessionTree struct { // removeFromRelayerSessions that removes the sessionTree from the RelayerSessionsManager. // It returns an error if the KVStore fails to be created. // TODO_BETA(@red-0ne): When starting a new session, check how many relays the app can handle. +// See the TODO next to the `sessionTree` struct definition for more details. func NewSessionTree( sessionHeader *sessiontypes.SessionHeader, supplierOperatorAddress *cosmostypes.AccAddress, diff --git a/x/tokenomics/keeper/token_logic_modules.go b/x/tokenomics/keeper/token_logic_modules.go index a05b1aee2..72c5bf2b7 100644 --- a/x/tokenomics/keeper/token_logic_modules.go +++ b/x/tokenomics/keeper/token_logic_modules.go @@ -26,12 +26,10 @@ import ( const ( // Governance parameters for the TLMGlobalMint module - // TODO_BETA_TEST(@olshansk): Remove this. It is an ephemeral placeholder before - // real values are introduced. When this is changed to a governance param, - // make sure to also add the necessary unit tests. + // TODO_UPNEXT(@olshansk, #732): Make this a governance parameter and give it a non-zero value + tests. MintPerClaimGlobalInflation = 0.0000000 - // TODO_BETA: Make all of the governance params + // TODO_BETA(@bryanchriswhite): Make all of the governance params MintAllocationDAO = 0.1 MintAllocationProposer = 0.05 MintAllocationSupplier = 0.7 @@ -97,7 +95,7 @@ type TokenLogicModuleProcessor func( var tokenLogicModuleProcessorMap = map[TokenLogicModule]TokenLogicModuleProcessor{ TLMRelayBurnEqualsMint: Keeper.TokenLogicModuleRelayBurnEqualsMint, TLMGlobalMint: Keeper.TokenLogicModuleGlobalMint, - // TODO_BETA_UPNEXT(@Olshansky): Uncomment this and add tests. + // TODO_UPNEXT(@olshansk, #732): Uncomment this, finish implementation, and add tests. // TLMGlobalMintReimbursementRequest: Keeper.TokenLogicModuleGlobalMintReimbursementRequest, } @@ -423,10 +421,10 @@ func (k Keeper) TokenLogicModuleGlobalMintReimbursementRequest( newMintCoins, _ := calculateGlobalPerClaimMintInflationFromSettlementAmount(settlementCoins) /* - TODO_UPNEXT_BETA(@Olshansky): Finish implementing this: + TODO_UPNEXT(@olshansk, #732): Finish implementing this: 1. Overcharge the application (reduce stake and burn app module tokens) 2. Send the overcharge to the DAO/PNF address - 3. Add extensive tests for this. + 3. Add necessary tests. */ // Prepare and emit the event for the application being overcharged diff --git a/x/tokenomics/keeper/token_logic_modules_test.go b/x/tokenomics/keeper/token_logic_modules_test.go index 50fecad21..e842abe59 100644 --- a/x/tokenomics/keeper/token_logic_modules_test.go +++ b/x/tokenomics/keeper/token_logic_modules_test.go @@ -33,8 +33,11 @@ func init() { cmd.InitSDKConfig() } -// TODO_IN_THIS_PR: Tests to add or list -// claimSettlementAmount > maxClaimableAmount +// TODO_IN_THIS_PR: Add these tests or update existing tests to account for it. +// func TestProcessTokenLogicModules_HandleMaxClaimGreaterActualClaim(t *testing.T) {...} +// TODO_UPNEXT(@olshansk, #732): Add the following tests +// func TestProcessTokenLogicModules_ValidateAppOverServicingEvent(t *testing.T) {...} +// func TestProcessTokenLogicModules_ValidateAppReimbursedRequestEvent(t *testing.T) {...} func TestProcessTokenLogicModules_HandleAppGoingIntoDebt(t *testing.T) { keepers, ctx := testkeeper.NewTokenomicsModuleKeepers(t, nil) diff --git a/x/tokenomics/keeper/update_relay_mining_difficulty.go b/x/tokenomics/keeper/update_relay_mining_difficulty.go index d563db86b..e93b1574d 100644 --- a/x/tokenomics/keeper/update_relay_mining_difficulty.go +++ b/x/tokenomics/keeper/update_relay_mining_difficulty.go @@ -183,6 +183,9 @@ func computeEma(alpha *big.Float, prevEma, currValue uint64) uint64 { return newEma } +// newDefaultRelayMiningDifficulty is a helper that creates a new RelayMiningDifficulty +// structure if one is not available. It is often used to set the default when a service's +// difficulty is being initialized for the first time. func newDefaultRelayMiningDifficulty( ctx context.Context, methodLogger log.Logger, @@ -192,8 +195,7 @@ func newDefaultRelayMiningDifficulty( logger := methodLogger.With("helper", "newDefaultRelayMiningDifficulty") logger.Warn(types.ErrTokenomicsMissingRelayMiningDifficulty.Wrapf( "No previous relay mining difficulty found for service %s. Creating a temporary relay mining difficulty with %d relays and default target hash %x", - serviceId, numRelays, - ).Error()) + serviceId, numRelays, prooftypes.DefaultRelayDifficultyTargetHash).Error()) return tokenomicstypes.RelayMiningDifficulty{ ServiceId: serviceId, From 0e725a44a0daba5368af781215926d50e233dc29 Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Thu, 22 Aug 2024 16:53:10 -0400 Subject: [PATCH 06/31] Remove everything related to TLMGlobalMintReimbursementRequest --- api/poktroll/tokenomics/event.pulsar.go | 792 +-------------------- proto/poktroll/tokenomics/event.proto | 11 +- x/tokenomics/keeper/token_logic_modules.go | 47 -- x/tokenomics/types/event.pb.go | 432 ++--------- 4 files changed, 87 insertions(+), 1195 deletions(-) diff --git a/api/poktroll/tokenomics/event.pulsar.go b/api/poktroll/tokenomics/event.pulsar.go index afb700d4a..25caeaa82 100644 --- a/api/poktroll/tokenomics/event.pulsar.go +++ b/api/poktroll/tokenomics/event.pulsar.go @@ -2459,633 +2459,6 @@ func (x *fastReflection_EventApplicationOverserviced) ProtoMethods() *protoiface } } -var ( - md_EventApplicationReimbursementRequest protoreflect.MessageDescriptor - fd_EventApplicationReimbursementRequest_application_addr protoreflect.FieldDescriptor - fd_EventApplicationReimbursementRequest_service_id protoreflect.FieldDescriptor - fd_EventApplicationReimbursementRequest_session_id protoreflect.FieldDescriptor - fd_EventApplicationReimbursementRequest_amount protoreflect.FieldDescriptor -) - -func init() { - file_poktroll_tokenomics_event_proto_init() - md_EventApplicationReimbursementRequest = File_poktroll_tokenomics_event_proto.Messages().ByName("EventApplicationReimbursementRequest") - fd_EventApplicationReimbursementRequest_application_addr = md_EventApplicationReimbursementRequest.Fields().ByName("application_addr") - fd_EventApplicationReimbursementRequest_service_id = md_EventApplicationReimbursementRequest.Fields().ByName("service_id") - fd_EventApplicationReimbursementRequest_session_id = md_EventApplicationReimbursementRequest.Fields().ByName("session_id") - fd_EventApplicationReimbursementRequest_amount = md_EventApplicationReimbursementRequest.Fields().ByName("amount") -} - -var _ protoreflect.Message = (*fastReflection_EventApplicationReimbursementRequest)(nil) - -type fastReflection_EventApplicationReimbursementRequest EventApplicationReimbursementRequest - -func (x *EventApplicationReimbursementRequest) ProtoReflect() protoreflect.Message { - return (*fastReflection_EventApplicationReimbursementRequest)(x) -} - -func (x *EventApplicationReimbursementRequest) slowProtoReflect() protoreflect.Message { - mi := &file_poktroll_tokenomics_event_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_EventApplicationReimbursementRequest_messageType fastReflection_EventApplicationReimbursementRequest_messageType -var _ protoreflect.MessageType = fastReflection_EventApplicationReimbursementRequest_messageType{} - -type fastReflection_EventApplicationReimbursementRequest_messageType struct{} - -func (x fastReflection_EventApplicationReimbursementRequest_messageType) Zero() protoreflect.Message { - return (*fastReflection_EventApplicationReimbursementRequest)(nil) -} -func (x fastReflection_EventApplicationReimbursementRequest_messageType) New() protoreflect.Message { - return new(fastReflection_EventApplicationReimbursementRequest) -} -func (x fastReflection_EventApplicationReimbursementRequest_messageType) Descriptor() protoreflect.MessageDescriptor { - return md_EventApplicationReimbursementRequest -} - -// Descriptor returns message descriptor, which contains only the protobuf -// type information for the message. -func (x *fastReflection_EventApplicationReimbursementRequest) Descriptor() protoreflect.MessageDescriptor { - return md_EventApplicationReimbursementRequest -} - -// 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_EventApplicationReimbursementRequest) Type() protoreflect.MessageType { - return _fastReflection_EventApplicationReimbursementRequest_messageType -} - -// New returns a newly allocated and mutable empty message. -func (x *fastReflection_EventApplicationReimbursementRequest) New() protoreflect.Message { - return new(fastReflection_EventApplicationReimbursementRequest) -} - -// Interface unwraps the message reflection interface and -// returns the underlying ProtoMessage interface. -func (x *fastReflection_EventApplicationReimbursementRequest) Interface() protoreflect.ProtoMessage { - return (*EventApplicationReimbursementRequest)(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_EventApplicationReimbursementRequest) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { - if x.ApplicationAddr != "" { - value := protoreflect.ValueOfString(x.ApplicationAddr) - if !f(fd_EventApplicationReimbursementRequest_application_addr, value) { - return - } - } - if x.ServiceId != "" { - value := protoreflect.ValueOfString(x.ServiceId) - if !f(fd_EventApplicationReimbursementRequest_service_id, value) { - return - } - } - if x.SessionId != "" { - value := protoreflect.ValueOfString(x.SessionId) - if !f(fd_EventApplicationReimbursementRequest_session_id, value) { - return - } - } - if x.Amount != nil { - value := protoreflect.ValueOfMessage(x.Amount.ProtoReflect()) - if !f(fd_EventApplicationReimbursementRequest_amount, 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_EventApplicationReimbursementRequest) Has(fd protoreflect.FieldDescriptor) bool { - switch fd.FullName() { - case "poktroll.tokenomics.EventApplicationReimbursementRequest.application_addr": - return x.ApplicationAddr != "" - case "poktroll.tokenomics.EventApplicationReimbursementRequest.service_id": - return x.ServiceId != "" - case "poktroll.tokenomics.EventApplicationReimbursementRequest.session_id": - return x.SessionId != "" - case "poktroll.tokenomics.EventApplicationReimbursementRequest.amount": - return x.Amount != nil - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.tokenomics.EventApplicationReimbursementRequest")) - } - panic(fmt.Errorf("message poktroll.tokenomics.EventApplicationReimbursementRequest 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_EventApplicationReimbursementRequest) Clear(fd protoreflect.FieldDescriptor) { - switch fd.FullName() { - case "poktroll.tokenomics.EventApplicationReimbursementRequest.application_addr": - x.ApplicationAddr = "" - case "poktroll.tokenomics.EventApplicationReimbursementRequest.service_id": - x.ServiceId = "" - case "poktroll.tokenomics.EventApplicationReimbursementRequest.session_id": - x.SessionId = "" - case "poktroll.tokenomics.EventApplicationReimbursementRequest.amount": - x.Amount = nil - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.tokenomics.EventApplicationReimbursementRequest")) - } - panic(fmt.Errorf("message poktroll.tokenomics.EventApplicationReimbursementRequest 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_EventApplicationReimbursementRequest) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { - switch descriptor.FullName() { - case "poktroll.tokenomics.EventApplicationReimbursementRequest.application_addr": - value := x.ApplicationAddr - return protoreflect.ValueOfString(value) - case "poktroll.tokenomics.EventApplicationReimbursementRequest.service_id": - value := x.ServiceId - return protoreflect.ValueOfString(value) - case "poktroll.tokenomics.EventApplicationReimbursementRequest.session_id": - value := x.SessionId - return protoreflect.ValueOfString(value) - case "poktroll.tokenomics.EventApplicationReimbursementRequest.amount": - value := x.Amount - return protoreflect.ValueOfMessage(value.ProtoReflect()) - default: - if descriptor.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.tokenomics.EventApplicationReimbursementRequest")) - } - panic(fmt.Errorf("message poktroll.tokenomics.EventApplicationReimbursementRequest 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_EventApplicationReimbursementRequest) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { - switch fd.FullName() { - case "poktroll.tokenomics.EventApplicationReimbursementRequest.application_addr": - x.ApplicationAddr = value.Interface().(string) - case "poktroll.tokenomics.EventApplicationReimbursementRequest.service_id": - x.ServiceId = value.Interface().(string) - case "poktroll.tokenomics.EventApplicationReimbursementRequest.session_id": - x.SessionId = value.Interface().(string) - case "poktroll.tokenomics.EventApplicationReimbursementRequest.amount": - x.Amount = value.Message().Interface().(*v1beta1.Coin) - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.tokenomics.EventApplicationReimbursementRequest")) - } - panic(fmt.Errorf("message poktroll.tokenomics.EventApplicationReimbursementRequest 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_EventApplicationReimbursementRequest) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { - switch fd.FullName() { - case "poktroll.tokenomics.EventApplicationReimbursementRequest.amount": - if x.Amount == nil { - x.Amount = new(v1beta1.Coin) - } - return protoreflect.ValueOfMessage(x.Amount.ProtoReflect()) - case "poktroll.tokenomics.EventApplicationReimbursementRequest.application_addr": - panic(fmt.Errorf("field application_addr of message poktroll.tokenomics.EventApplicationReimbursementRequest is not mutable")) - case "poktroll.tokenomics.EventApplicationReimbursementRequest.service_id": - panic(fmt.Errorf("field service_id of message poktroll.tokenomics.EventApplicationReimbursementRequest is not mutable")) - case "poktroll.tokenomics.EventApplicationReimbursementRequest.session_id": - panic(fmt.Errorf("field session_id of message poktroll.tokenomics.EventApplicationReimbursementRequest is not mutable")) - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.tokenomics.EventApplicationReimbursementRequest")) - } - panic(fmt.Errorf("message poktroll.tokenomics.EventApplicationReimbursementRequest 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_EventApplicationReimbursementRequest) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { - switch fd.FullName() { - case "poktroll.tokenomics.EventApplicationReimbursementRequest.application_addr": - return protoreflect.ValueOfString("") - case "poktroll.tokenomics.EventApplicationReimbursementRequest.service_id": - return protoreflect.ValueOfString("") - case "poktroll.tokenomics.EventApplicationReimbursementRequest.session_id": - return protoreflect.ValueOfString("") - case "poktroll.tokenomics.EventApplicationReimbursementRequest.amount": - m := new(v1beta1.Coin) - return protoreflect.ValueOfMessage(m.ProtoReflect()) - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.tokenomics.EventApplicationReimbursementRequest")) - } - panic(fmt.Errorf("message poktroll.tokenomics.EventApplicationReimbursementRequest 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_EventApplicationReimbursementRequest) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { - switch d.FullName() { - default: - panic(fmt.Errorf("%s is not a oneof field in poktroll.tokenomics.EventApplicationReimbursementRequest", 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_EventApplicationReimbursementRequest) 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_EventApplicationReimbursementRequest) 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_EventApplicationReimbursementRequest) 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_EventApplicationReimbursementRequest) ProtoMethods() *protoiface.Methods { - size := func(input protoiface.SizeInput) protoiface.SizeOutput { - x := input.Message.Interface().(*EventApplicationReimbursementRequest) - 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.ApplicationAddr) - if l > 0 { - n += 1 + l + runtime.Sov(uint64(l)) - } - l = len(x.ServiceId) - if l > 0 { - n += 1 + l + runtime.Sov(uint64(l)) - } - l = len(x.SessionId) - if l > 0 { - n += 1 + l + runtime.Sov(uint64(l)) - } - if x.Amount != nil { - l = options.Size(x.Amount) - 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().(*EventApplicationReimbursementRequest) - 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.Amount != nil { - encoded, err := options.Marshal(x.Amount) - 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] = 0x22 - } - if len(x.SessionId) > 0 { - i -= len(x.SessionId) - copy(dAtA[i:], x.SessionId) - i = runtime.EncodeVarint(dAtA, i, uint64(len(x.SessionId))) - i-- - dAtA[i] = 0x1a - } - if len(x.ServiceId) > 0 { - i -= len(x.ServiceId) - copy(dAtA[i:], x.ServiceId) - i = runtime.EncodeVarint(dAtA, i, uint64(len(x.ServiceId))) - i-- - dAtA[i] = 0x12 - } - if len(x.ApplicationAddr) > 0 { - i -= len(x.ApplicationAddr) - copy(dAtA[i:], x.ApplicationAddr) - i = runtime.EncodeVarint(dAtA, i, uint64(len(x.ApplicationAddr))) - 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().(*EventApplicationReimbursementRequest) - 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: EventApplicationReimbursementRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: EventApplicationReimbursementRequest: 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 ApplicationAddr", 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.ApplicationAddr = 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 ServiceId", 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.ServiceId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 2 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field SessionId", 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.SessionId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 4: - if wireType != 2 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Amount", 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.Amount == nil { - x.Amount = &v1beta1.Coin{} - } - if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.Amount); err != nil { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := runtime.Skip(dAtA[iNdEx:]) - if err != nil { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength - } - if (iNdEx + skippy) > l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - if !options.DiscardUnknown { - x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) - } - iNdEx += skippy - } - } - - if iNdEx > l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil - } - return &protoiface.Methods{ - NoUnkeyedLiterals: struct{}{}, - Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, - Size: size, - Marshal: marshal, - Unmarshal: unmarshal, - Merge: nil, - CheckInitialized: nil, - } -} - // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.0 @@ -3409,67 +2782,6 @@ func (x *EventApplicationOverserviced) GetEffectiveBurn() *v1beta1.Coin { return nil } -// EventApplicationReimbursementRequest is emitted when an application requests -// a reimbursement -type EventApplicationReimbursementRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - ApplicationAddr string `protobuf:"bytes,1,opt,name=application_addr,json=applicationAddr,proto3" json:"application_addr,omitempty"` - ServiceId string `protobuf:"bytes,2,opt,name=service_id,json=serviceId,proto3" json:"service_id,omitempty"` - SessionId string `protobuf:"bytes,3,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` - Amount *v1beta1.Coin `protobuf:"bytes,4,opt,name=amount,proto3" json:"amount,omitempty"` -} - -func (x *EventApplicationReimbursementRequest) Reset() { - *x = EventApplicationReimbursementRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_poktroll_tokenomics_event_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *EventApplicationReimbursementRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EventApplicationReimbursementRequest) ProtoMessage() {} - -// Deprecated: Use EventApplicationReimbursementRequest.ProtoReflect.Descriptor instead. -func (*EventApplicationReimbursementRequest) Descriptor() ([]byte, []int) { - return file_poktroll_tokenomics_event_proto_rawDescGZIP(), []int{4} -} - -func (x *EventApplicationReimbursementRequest) GetApplicationAddr() string { - if x != nil { - return x.ApplicationAddr - } - return "" -} - -func (x *EventApplicationReimbursementRequest) GetServiceId() string { - if x != nil { - return x.ServiceId - } - return "" -} - -func (x *EventApplicationReimbursementRequest) GetSessionId() string { - if x != nil { - return x.SessionId - } - return "" -} - -func (x *EventApplicationReimbursementRequest) GetAmount() *v1beta1.Coin { - if x != nil { - return x.Amount - } - return nil -} - var File_poktroll_tokenomics_event_proto protoreflect.FileDescriptor var file_poktroll_tokenomics_event_proto_rawDesc = []byte{ @@ -3552,37 +2864,25 @@ var file_poktroll_tokenomics_event_proto_rawDesc = []byte{ 0x65, 0x5f, 0x62, 0x75, 0x72, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x0d, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, - 0x76, 0x65, 0x42, 0x75, 0x72, 0x6e, 0x22, 0xc2, 0x01, 0x0a, 0x24, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x69, 0x6d, 0x62, - 0x75, 0x72, 0x73, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x29, 0x0a, 0x10, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, - 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x61, 0x70, 0x70, 0x6c, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x31, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, - 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, - 0x6f, 0x69, 0x6e, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x2a, 0x60, 0x0a, 0x15, 0x43, - 0x6c, 0x61, 0x69, 0x6d, 0x45, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x1d, 0x45, 0x58, 0x50, 0x49, 0x52, 0x41, 0x54, 0x49, - 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, - 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x52, 0x4f, 0x4f, 0x46, - 0x5f, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x52, - 0x4f, 0x4f, 0x46, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x02, 0x42, 0xb8, 0x01, - 0x0a, 0x17, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2e, 0x74, - 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0x42, 0x0a, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x24, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, - 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x6f, 0x6b, 0x74, 0x72, 0x6f, - 0x6c, 0x6c, 0x2f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0xa2, 0x02, 0x03, - 0x50, 0x54, 0x58, 0xaa, 0x02, 0x13, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2e, 0x54, - 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0xca, 0x02, 0x13, 0x50, 0x6f, 0x6b, 0x74, - 0x72, 0x6f, 0x6c, 0x6c, 0x5c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0xe2, - 0x02, 0x1f, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x5c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, - 0x6f, 0x6d, 0x69, 0x63, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0xea, 0x02, 0x14, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x3a, 0x3a, 0x54, 0x6f, - 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x76, 0x65, 0x42, 0x75, 0x72, 0x6e, 0x2a, 0x60, 0x0a, 0x15, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x45, + 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, + 0x21, 0x0a, 0x1d, 0x45, 0x58, 0x50, 0x49, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, + 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, + 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x4d, 0x49, 0x53, 0x53, + 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x49, + 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x02, 0x42, 0xb8, 0x01, 0x0a, 0x17, 0x63, 0x6f, 0x6d, + 0x2e, 0x70, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2e, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, + 0x6d, 0x69, 0x63, 0x73, 0x42, 0x0a, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, + 0x50, 0x01, 0x5a, 0x24, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, + 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2f, 0x74, 0x6f, + 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0xa2, 0x02, 0x03, 0x50, 0x54, 0x58, 0xaa, 0x02, + 0x13, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, + 0x6d, 0x69, 0x63, 0x73, 0xca, 0x02, 0x13, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x5c, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0xe2, 0x02, 0x1f, 0x50, 0x6f, 0x6b, + 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x5c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, + 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x14, 0x50, + 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x3a, 0x3a, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, + 0x69, 0x63, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -3598,31 +2898,29 @@ func file_poktroll_tokenomics_event_proto_rawDescGZIP() []byte { } var file_poktroll_tokenomics_event_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_poktroll_tokenomics_event_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_poktroll_tokenomics_event_proto_msgTypes = make([]protoimpl.MessageInfo, 4) var file_poktroll_tokenomics_event_proto_goTypes = []interface{}{ - (ClaimExpirationReason)(0), // 0: poktroll.tokenomics.ClaimExpirationReason - (*EventClaimExpired)(nil), // 1: poktroll.tokenomics.EventClaimExpired - (*EventClaimSettled)(nil), // 2: poktroll.tokenomics.EventClaimSettled - (*EventRelayMiningDifficultyUpdated)(nil), // 3: poktroll.tokenomics.EventRelayMiningDifficultyUpdated - (*EventApplicationOverserviced)(nil), // 4: poktroll.tokenomics.EventApplicationOverserviced - (*EventApplicationReimbursementRequest)(nil), // 5: poktroll.tokenomics.EventApplicationReimbursementRequest - (*proof.Claim)(nil), // 6: poktroll.proof.Claim - (proof.ProofRequirementReason)(0), // 7: poktroll.proof.ProofRequirementReason - (*v1beta1.Coin)(nil), // 8: cosmos.base.v1beta1.Coin + (ClaimExpirationReason)(0), // 0: poktroll.tokenomics.ClaimExpirationReason + (*EventClaimExpired)(nil), // 1: poktroll.tokenomics.EventClaimExpired + (*EventClaimSettled)(nil), // 2: poktroll.tokenomics.EventClaimSettled + (*EventRelayMiningDifficultyUpdated)(nil), // 3: poktroll.tokenomics.EventRelayMiningDifficultyUpdated + (*EventApplicationOverserviced)(nil), // 4: poktroll.tokenomics.EventApplicationOverserviced + (*proof.Claim)(nil), // 5: poktroll.proof.Claim + (proof.ProofRequirementReason)(0), // 6: poktroll.proof.ProofRequirementReason + (*v1beta1.Coin)(nil), // 7: cosmos.base.v1beta1.Coin } var file_poktroll_tokenomics_event_proto_depIdxs = []int32{ - 6, // 0: poktroll.tokenomics.EventClaimExpired.claim:type_name -> poktroll.proof.Claim + 5, // 0: poktroll.tokenomics.EventClaimExpired.claim:type_name -> poktroll.proof.Claim 0, // 1: poktroll.tokenomics.EventClaimExpired.expiration_reason:type_name -> poktroll.tokenomics.ClaimExpirationReason - 6, // 2: poktroll.tokenomics.EventClaimSettled.claim:type_name -> poktroll.proof.Claim - 7, // 3: poktroll.tokenomics.EventClaimSettled.proof_requirement:type_name -> poktroll.proof.ProofRequirementReason - 8, // 4: poktroll.tokenomics.EventApplicationOverserviced.expected_burn:type_name -> cosmos.base.v1beta1.Coin - 8, // 5: poktroll.tokenomics.EventApplicationOverserviced.effective_burn:type_name -> cosmos.base.v1beta1.Coin - 8, // 6: poktroll.tokenomics.EventApplicationReimbursementRequest.amount:type_name -> cosmos.base.v1beta1.Coin - 7, // [7:7] is the sub-list for method output_type - 7, // [7:7] 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 + 5, // 2: poktroll.tokenomics.EventClaimSettled.claim:type_name -> poktroll.proof.Claim + 6, // 3: poktroll.tokenomics.EventClaimSettled.proof_requirement:type_name -> poktroll.proof.ProofRequirementReason + 7, // 4: poktroll.tokenomics.EventApplicationOverserviced.expected_burn:type_name -> cosmos.base.v1beta1.Coin + 7, // 5: poktroll.tokenomics.EventApplicationOverserviced.effective_burn:type_name -> cosmos.base.v1beta1.Coin + 6, // [6:6] is the sub-list for method output_type + 6, // [6:6] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name } func init() { file_poktroll_tokenomics_event_proto_init() } @@ -3679,18 +2977,6 @@ func file_poktroll_tokenomics_event_proto_init() { return nil } } - file_poktroll_tokenomics_event_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EventApplicationReimbursementRequest); 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{ @@ -3698,7 +2984,7 @@ func file_poktroll_tokenomics_event_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_poktroll_tokenomics_event_proto_rawDesc, NumEnums: 1, - NumMessages: 5, + NumMessages: 4, NumExtensions: 0, NumServices: 0, }, diff --git a/proto/poktroll/tokenomics/event.proto b/proto/poktroll/tokenomics/event.proto index f5af15a76..9b07d8ae1 100644 --- a/proto/poktroll/tokenomics/event.proto +++ b/proto/poktroll/tokenomics/event.proto @@ -57,13 +57,4 @@ message EventApplicationOverserviced { // most likely equal to the application's stake divided by the number of suppliers // in a session. cosmos.base.v1beta1.Coin effective_burn = 4; -} - -// EventApplicationReimbursementRequest is emitted when an application requests -// a reimbursement -message EventApplicationReimbursementRequest { - string application_addr = 1; - string service_id = 2; - string session_id = 3; - cosmos.base.v1beta1.Coin amount = 4; -} +} \ No newline at end of file diff --git a/x/tokenomics/keeper/token_logic_modules.go b/x/tokenomics/keeper/token_logic_modules.go index 72c5bf2b7..3db0c9b41 100644 --- a/x/tokenomics/keeper/token_logic_modules.go +++ b/x/tokenomics/keeper/token_logic_modules.go @@ -50,20 +50,11 @@ const ( // on global governance parameters in order to reward the participants providing // services while keeping inflation in check. TLMGlobalMint - - // TLMGlobalMintReimbursementRequest is the token logic module that complements - // TLMGlobalMint to enable permissionless demand. In order to prevent self-dealing - // attacks, applications will be overcharged by the amount equal to global inflation, - // those funds will be sent to the DAO/PNF, and an event will be emitted to track - // and send reimbursements; managed offchain by PNF. - // TODO_POST_MAINNET: Introduce proper tokenomics based on the research done by @rawthil and @shane. - TLMGlobalMintReimbursementRequest ) var tokenLogicModuleStrings = [...]string{ "TLMRelayBurnEqualsMint", "TLMGlobalMint", - "TLMGlobalMintReimbursementRequest", } func (tlm TokenLogicModule) String() string { @@ -95,8 +86,6 @@ type TokenLogicModuleProcessor func( var tokenLogicModuleProcessorMap = map[TokenLogicModule]TokenLogicModuleProcessor{ TLMRelayBurnEqualsMint: Keeper.TokenLogicModuleRelayBurnEqualsMint, TLMGlobalMint: Keeper.TokenLogicModuleGlobalMint, - // TODO_UPNEXT(@olshansk, #732): Uncomment this, finish implementation, and add tests. - // TLMGlobalMintReimbursementRequest: Keeper.TokenLogicModuleGlobalMintReimbursementRequest, } func init() { @@ -406,42 +395,6 @@ func (k Keeper) TokenLogicModuleGlobalMint( return nil } -// TokenLogicModuleGlobalMintReimbursementRequest processes the business logic for the GlobalMintReimbursementRequest TLM. -func (k Keeper) TokenLogicModuleGlobalMintReimbursementRequest( - ctx context.Context, - service *sharedtypes.Service, - sessionHeader *sessiontypes.SessionHeader, - application *apptypes.Application, - supplier *sharedtypes.Supplier, - settlementCoins cosmostypes.Coin, - relayMiningDifficulty *tokenomictypes.RelayMiningDifficulty, -) error { - - // Determine how much new uPOKT to mint based on global inflation - newMintCoins, _ := calculateGlobalPerClaimMintInflationFromSettlementAmount(settlementCoins) - - /* - TODO_UPNEXT(@olshansk, #732): Finish implementing this: - 1. Overcharge the application (reduce stake and burn app module tokens) - 2. Send the overcharge to the DAO/PNF address - 3. Add necessary tests. - */ - - // Prepare and emit the event for the application being overcharged - reimbursementRequestEvent := tokenomictypes.EventApplicationReimbursementRequest{ - ApplicationAddr: application.Address, - ServiceId: service.Id, - SessionId: sessionHeader.SessionId, - Amount: &newMintCoins[0], - } - eventManager := cosmostypes.UnwrapSDKContext(ctx).EventManager() - if err := eventManager.EmitTypedEvent(&reimbursementRequestEvent); err != nil { - return tokenomicstypes.ErrTokenomicsEmittingEventFailed.Wrapf("error emitting event %v", reimbursementRequestEvent) - } - - return nil -} - // sendRewardsToAccount sends (settlementAmtFloat * allocation) tokens from the // tokenomics module account to the specified address. func (k Keeper) sendRewardsToAccount( diff --git a/x/tokenomics/types/event.pb.go b/x/tokenomics/types/event.pb.go index 27a0d9614..648c6afbb 100644 --- a/x/tokenomics/types/event.pb.go +++ b/x/tokenomics/types/event.pb.go @@ -350,139 +350,64 @@ func (m *EventApplicationOverserviced) GetEffectiveBurn() *types1.Coin { return nil } -// EventApplicationReimbursementRequest is emitted when an application requests -// a reimbursement -type EventApplicationReimbursementRequest struct { - ApplicationAddr string `protobuf:"bytes,1,opt,name=application_addr,json=applicationAddr,proto3" json:"application_addr,omitempty"` - ServiceId string `protobuf:"bytes,2,opt,name=service_id,json=serviceId,proto3" json:"service_id,omitempty"` - SessionId string `protobuf:"bytes,3,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` - Amount *types1.Coin `protobuf:"bytes,4,opt,name=amount,proto3" json:"amount,omitempty"` -} - -func (m *EventApplicationReimbursementRequest) Reset() { *m = EventApplicationReimbursementRequest{} } -func (m *EventApplicationReimbursementRequest) String() string { return proto.CompactTextString(m) } -func (*EventApplicationReimbursementRequest) ProtoMessage() {} -func (*EventApplicationReimbursementRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_a78874bbf91a58c7, []int{4} -} -func (m *EventApplicationReimbursementRequest) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *EventApplicationReimbursementRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_EventApplicationReimbursementRequest.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 *EventApplicationReimbursementRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_EventApplicationReimbursementRequest.Merge(m, src) -} -func (m *EventApplicationReimbursementRequest) XXX_Size() int { - return m.Size() -} -func (m *EventApplicationReimbursementRequest) XXX_DiscardUnknown() { - xxx_messageInfo_EventApplicationReimbursementRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_EventApplicationReimbursementRequest proto.InternalMessageInfo - -func (m *EventApplicationReimbursementRequest) GetApplicationAddr() string { - if m != nil { - return m.ApplicationAddr - } - return "" -} - -func (m *EventApplicationReimbursementRequest) GetServiceId() string { - if m != nil { - return m.ServiceId - } - return "" -} - -func (m *EventApplicationReimbursementRequest) GetSessionId() string { - if m != nil { - return m.SessionId - } - return "" -} - -func (m *EventApplicationReimbursementRequest) GetAmount() *types1.Coin { - if m != nil { - return m.Amount - } - return nil -} - func init() { proto.RegisterEnum("poktroll.tokenomics.ClaimExpirationReason", ClaimExpirationReason_name, ClaimExpirationReason_value) proto.RegisterType((*EventClaimExpired)(nil), "poktroll.tokenomics.EventClaimExpired") proto.RegisterType((*EventClaimSettled)(nil), "poktroll.tokenomics.EventClaimSettled") proto.RegisterType((*EventRelayMiningDifficultyUpdated)(nil), "poktroll.tokenomics.EventRelayMiningDifficultyUpdated") proto.RegisterType((*EventApplicationOverserviced)(nil), "poktroll.tokenomics.EventApplicationOverserviced") - proto.RegisterType((*EventApplicationReimbursementRequest)(nil), "poktroll.tokenomics.EventApplicationReimbursementRequest") } func init() { proto.RegisterFile("poktroll/tokenomics/event.proto", fileDescriptor_a78874bbf91a58c7) } var fileDescriptor_a78874bbf91a58c7 = []byte{ - // 786 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x55, 0xcd, 0x6e, 0xeb, 0x44, - 0x14, 0x8e, 0x73, 0x73, 0xaf, 0x94, 0xb9, 0x37, 0x6d, 0x32, 0x97, 0x8a, 0x50, 0xee, 0x4d, 0x7a, - 0x03, 0x42, 0xa5, 0xa8, 0xb6, 0xda, 0x4a, 0xac, 0x50, 0x45, 0x92, 0xba, 0xd4, 0x12, 0x4d, 0x22, - 0xa7, 0x45, 0x88, 0x8d, 0x71, 0xec, 0x93, 0x64, 0x68, 0x3c, 0xe3, 0xce, 0x8c, 0x93, 0xf4, 0x2d, - 0x78, 0x00, 0x5e, 0x80, 0x05, 0x2f, 0xc1, 0x8a, 0x65, 0x97, 0xac, 0x2a, 0xd4, 0xee, 0xba, 0xe2, - 0x11, 0x90, 0xc7, 0xce, 0x4f, 0xd3, 0x02, 0x62, 0xc9, 0x26, 0x99, 0x7c, 0xe7, 0x3b, 0x7f, 0xdf, - 0x9c, 0x39, 0x41, 0xd5, 0x90, 0x5d, 0x48, 0xce, 0x46, 0x23, 0x43, 0xb2, 0x0b, 0xa0, 0x2c, 0x20, - 0x9e, 0x30, 0x60, 0x0c, 0x54, 0xea, 0x21, 0x67, 0x92, 0xe1, 0xd7, 0x33, 0x82, 0xbe, 0x20, 0x6c, - 0x56, 0x3c, 0x26, 0x02, 0x26, 0x8c, 0x9e, 0x2b, 0xc0, 0x18, 0xef, 0xf5, 0x40, 0xba, 0x7b, 0x86, - 0xc7, 0x08, 0x4d, 0x9c, 0x36, 0xdf, 0x1b, 0xb0, 0x01, 0x53, 0x47, 0x23, 0x3e, 0xa5, 0xe8, 0xe6, - 0x3c, 0x57, 0xc8, 0x19, 0xeb, 0x1b, 0xf2, 0x2a, 0x04, 0x91, 0xd8, 0x6a, 0xbf, 0x64, 0x51, 0xc9, - 0x8c, 0xd3, 0x36, 0x47, 0x2e, 0x09, 0xcc, 0x69, 0x48, 0x38, 0xf8, 0xf8, 0x73, 0xf4, 0xdc, 0x8b, - 0x7f, 0x97, 0xb5, 0x2d, 0x6d, 0xfb, 0xe5, 0xfe, 0x86, 0x3e, 0x2f, 0x46, 0x45, 0xd0, 0x15, 0xb9, - 0x91, 0xbf, 0xbf, 0xa9, 0x26, 0x3c, 0x3b, 0xf9, 0xc2, 0xbb, 0x08, 0xd1, 0x28, 0x70, 0x38, 0x8c, - 0xdc, 0x2b, 0x51, 0xce, 0x6e, 0x69, 0xdb, 0xb9, 0xc6, 0xda, 0xfd, 0x4d, 0x75, 0x09, 0xb5, 0xf3, - 0x34, 0x0a, 0x6c, 0x75, 0xc4, 0x75, 0x54, 0x8a, 0x0d, 0x1e, 0x0b, 0xc2, 0x48, 0x82, 0x13, 0x51, - 0x22, 0x45, 0xf9, 0x99, 0xf2, 0xda, 0xb8, 0xbf, 0xa9, 0x3e, 0x36, 0xda, 0xeb, 0x34, 0x0a, 0x9a, - 0x09, 0x72, 0x1e, 0x03, 0x98, 0xa2, 0x12, 0xc4, 0x45, 0xbb, 0x92, 0x30, 0xea, 0x70, 0x70, 0x05, - 0xa3, 0xe5, 0xdc, 0x96, 0xb6, 0xbd, 0xb6, 0xbf, 0xa3, 0x3f, 0x21, 0xa1, 0xbe, 0xe8, 0x53, 0xb9, - 0xd8, 0xca, 0x23, 0x49, 0xf7, 0x28, 0x90, 0x5d, 0x84, 0x15, 0x62, 0xed, 0xe7, 0x07, 0x7a, 0x75, - 0x41, 0xca, 0xd1, 0xff, 0x4a, 0xaf, 0x1f, 0x50, 0x49, 0x95, 0xe4, 0x70, 0xb8, 0x8c, 0x08, 0x87, - 0x00, 0xa8, 0x4c, 0xf5, 0xfa, 0x64, 0xb5, 0xea, 0x4e, 0xfc, 0x69, 0x2f, 0x78, 0xcb, 0x5a, 0x3d, - 0x0a, 0x62, 0x17, 0xc3, 0x15, 0x7a, 0xed, 0xa7, 0x2c, 0x7a, 0xa7, 0xb4, 0x52, 0xe5, 0x9f, 0x12, - 0x4a, 0xe8, 0xe0, 0x88, 0xf4, 0xfb, 0xc4, 0x8b, 0x46, 0xf2, 0xea, 0x3c, 0xf4, 0x5d, 0x09, 0x3e, - 0x7e, 0x8b, 0x90, 0x00, 0x3e, 0x26, 0x1e, 0x38, 0xc4, 0x57, 0x02, 0xe6, 0xed, 0x7c, 0x8a, 0x58, - 0x3e, 0x3e, 0x44, 0x6f, 0x42, 0x0e, 0x63, 0x47, 0xba, 0x7c, 0x00, 0xd2, 0x19, 0xba, 0x62, 0xe8, - 0x0c, 0x61, 0xea, 0x00, 0xf5, 0x98, 0x0f, 0xbe, 0x12, 0x2d, 0x6f, 0x97, 0x63, 0xce, 0x99, 0xa2, - 0x9c, 0xb8, 0x62, 0x78, 0x02, 0x53, 0x33, 0xb1, 0xe3, 0x2f, 0xd0, 0x87, 0x14, 0x26, 0x7f, 0xeb, - 0xfe, 0x4c, 0xb9, 0xbf, 0x4f, 0x61, 0xf2, 0xa4, 0xf7, 0x2e, 0x7a, 0xad, 0xb2, 0x2f, 0xee, 0xc3, - 0x81, 0xc0, 0x55, 0x82, 0xe5, 0xe2, 0x8e, 0x61, 0xdc, 0x9a, 0xdd, 0x8e, 0x19, 0xb8, 0xf8, 0x33, - 0x84, 0xe3, 0x64, 0x2b, 0xec, 0xe7, 0x8a, 0xbd, 0x4e, 0x61, 0xb2, 0x4c, 0xae, 0xfd, 0xa9, 0xa1, - 0x37, 0x4a, 0x9e, 0x7a, 0x18, 0x8e, 0x88, 0xa7, 0xa6, 0xac, 0x3d, 0x06, 0x9e, 0xf6, 0xee, 0xe3, - 0x4f, 0x51, 0xd1, 0x5d, 0x98, 0x1c, 0xd7, 0xf7, 0x79, 0xaa, 0xcf, 0xfa, 0x12, 0x5e, 0xf7, 0x7d, - 0x8e, 0x3f, 0x42, 0x05, 0x11, 0xc5, 0x18, 0xf0, 0x84, 0x97, 0xc8, 0xf2, 0x6a, 0x06, 0x2a, 0xd2, - 0x21, 0x2a, 0xc0, 0x34, 0x04, 0x4f, 0x82, 0xef, 0xf4, 0x22, 0x4e, 0x55, 0xf3, 0x2f, 0xf7, 0x3f, - 0xd0, 0x93, 0xad, 0xa2, 0xc7, 0x5b, 0x45, 0x4f, 0xb7, 0x8a, 0xde, 0x64, 0x84, 0xda, 0xaf, 0x66, - 0xfc, 0x46, 0xc4, 0x29, 0xfe, 0x12, 0xad, 0x41, 0xbf, 0x0f, 0x9e, 0x24, 0x63, 0x48, 0x02, 0xe4, - 0xfe, 0x2d, 0x40, 0x61, 0xee, 0x10, 0x47, 0xa8, 0xfd, 0xaa, 0xa1, 0x8f, 0x57, 0x5b, 0xb6, 0x81, - 0x04, 0xbd, 0x88, 0x8b, 0x74, 0xc4, 0x2e, 0x23, 0x10, 0xf2, 0xbf, 0xb4, 0xfe, 0x70, 0x7e, 0xb2, - 0xab, 0xf3, 0xa3, 0xcc, 0x42, 0xc4, 0x51, 0xc8, 0xec, 0xba, 0xf3, 0x29, 0x62, 0xf9, 0x78, 0x0f, - 0xbd, 0x70, 0x03, 0x16, 0xa5, 0x8f, 0xe0, 0x1f, 0x7b, 0x49, 0x89, 0x3b, 0xdf, 0xa3, 0x8d, 0x27, - 0x97, 0x08, 0x7e, 0x87, 0xde, 0x9a, 0xdf, 0x76, 0x2c, 0xbb, 0x7e, 0x66, 0xb5, 0x5b, 0x8e, 0x6d, - 0xd6, 0xbb, 0xed, 0x96, 0x73, 0xde, 0xea, 0x76, 0xcc, 0xa6, 0x75, 0x6c, 0x99, 0x47, 0xc5, 0x0c, - 0x2e, 0xa1, 0x42, 0xc7, 0x6e, 0xb7, 0x8f, 0x9d, 0x53, 0xab, 0xdb, 0xb5, 0x5a, 0x5f, 0x15, 0xb5, - 0x05, 0x64, 0xb5, 0xbe, 0xa9, 0x7f, 0x6d, 0x1d, 0x15, 0xb3, 0x8d, 0xd3, 0xdf, 0x6e, 0x2b, 0xda, - 0xf5, 0x6d, 0x45, 0xfb, 0xe3, 0xb6, 0xa2, 0xfd, 0x78, 0x57, 0xc9, 0x5c, 0xdf, 0x55, 0x32, 0xbf, - 0xdf, 0x55, 0x32, 0xdf, 0x1d, 0x0c, 0x88, 0x1c, 0x46, 0x3d, 0xdd, 0x63, 0x81, 0x11, 0xbf, 0xd6, - 0x5d, 0x0a, 0x72, 0xc2, 0xf8, 0x85, 0x31, 0x5f, 0xf1, 0xd3, 0xe5, 0x3f, 0x14, 0xb5, 0xe9, 0x7b, - 0x2f, 0xd4, 0xaa, 0x3f, 0xf8, 0x2b, 0x00, 0x00, 0xff, 0xff, 0xed, 0x40, 0xd7, 0x5c, 0x74, 0x06, - 0x00, 0x00, + // 730 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x54, 0x4d, 0x4f, 0xdb, 0x48, + 0x18, 0x8e, 0x43, 0x58, 0x29, 0x03, 0x81, 0xc4, 0x2c, 0xda, 0x2c, 0x0b, 0x09, 0x64, 0xa5, 0x15, + 0xcb, 0x0a, 0x5b, 0x80, 0xb4, 0xa7, 0x15, 0xda, 0x24, 0x98, 0xc5, 0xd2, 0x92, 0x44, 0x0e, 0x54, + 0x55, 0x2f, 0x53, 0xc7, 0x7e, 0x93, 0x4c, 0x89, 0x67, 0xdc, 0xf1, 0x38, 0x09, 0xff, 0xa2, 0x3f, + 0xa0, 0x7f, 0xa0, 0x87, 0xfe, 0x8f, 0x1e, 0x39, 0xf6, 0x84, 0x2a, 0xb8, 0x71, 0xea, 0x4f, 0xa8, + 0x3c, 0xce, 0x57, 0x03, 0x55, 0xcf, 0xbd, 0x24, 0x93, 0xe7, 0x7d, 0x9e, 0xf7, 0xe3, 0x99, 0xc9, + 0x8b, 0x8a, 0x3e, 0xbb, 0x12, 0x9c, 0xf5, 0x7a, 0xba, 0x60, 0x57, 0x40, 0x99, 0x47, 0x9c, 0x40, + 0x87, 0x3e, 0x50, 0xa1, 0xf9, 0x9c, 0x09, 0xa6, 0xae, 0x8d, 0x09, 0xda, 0x94, 0xb0, 0x51, 0x70, + 0x58, 0xe0, 0xb1, 0x40, 0x6f, 0xd9, 0x01, 0xe8, 0xfd, 0x83, 0x16, 0x08, 0xfb, 0x40, 0x77, 0x18, + 0xa1, 0xb1, 0x68, 0xe3, 0xe7, 0x0e, 0xeb, 0x30, 0x79, 0xd4, 0xa3, 0xd3, 0x08, 0xdd, 0x98, 0xd4, + 0xf2, 0x39, 0x63, 0x6d, 0x5d, 0x5c, 0xfb, 0x10, 0xc4, 0xb1, 0xd2, 0xfb, 0x24, 0xca, 0x19, 0x51, + 0xd9, 0x6a, 0xcf, 0x26, 0x9e, 0x31, 0xf4, 0x09, 0x07, 0x57, 0xfd, 0x1b, 0x2d, 0x3a, 0xd1, 0xef, + 0xbc, 0xb2, 0xad, 0xec, 0x2e, 0x1d, 0xae, 0x6b, 0x93, 0x66, 0x64, 0x06, 0x4d, 0x92, 0x2b, 0xe9, + 0x87, 0xdb, 0x62, 0xcc, 0xb3, 0xe2, 0x2f, 0x75, 0x1f, 0x21, 0x1a, 0x7a, 0x98, 0x43, 0xcf, 0xbe, + 0x0e, 0xf2, 0xc9, 0x6d, 0x65, 0x37, 0x55, 0x59, 0x79, 0xb8, 0x2d, 0xce, 0xa0, 0x56, 0x9a, 0x86, + 0x9e, 0x25, 0x8f, 0x6a, 0x19, 0xe5, 0xa2, 0x80, 0xc3, 0x3c, 0x3f, 0x14, 0x80, 0x43, 0x4a, 0x44, + 0x90, 0x5f, 0x90, 0xaa, 0xf5, 0x87, 0xdb, 0xe2, 0xe3, 0xa0, 0xb5, 0x4a, 0x43, 0xaf, 0x1a, 0x23, + 0x97, 0x11, 0xa0, 0x52, 0x94, 0x83, 0xa8, 0x69, 0x5b, 0x10, 0x46, 0x31, 0x07, 0x3b, 0x60, 0x34, + 0x9f, 0xda, 0x56, 0x76, 0x57, 0x0e, 0xf7, 0xb4, 0x27, 0x2c, 0xd4, 0xa6, 0x73, 0x4a, 0x89, 0x25, + 0x15, 0x71, 0xb9, 0x47, 0x89, 0xac, 0x2c, 0xcc, 0x11, 0x4b, 0xef, 0xbe, 0xf2, 0xab, 0x09, 0x42, + 0xf4, 0x7e, 0x28, 0xbf, 0x5e, 0xa1, 0x9c, 0x6c, 0x09, 0x73, 0x78, 0x1d, 0x12, 0x0e, 0x1e, 0x50, + 0x31, 0xf2, 0xeb, 0x8f, 0xf9, 0xae, 0x1b, 0xd1, 0xa7, 0x35, 0xe5, 0xcd, 0x7a, 0xf5, 0x28, 0x89, + 0x95, 0xf5, 0xe7, 0xe8, 0xa5, 0xb7, 0x49, 0xb4, 0x23, 0xbd, 0x92, 0xed, 0x9f, 0x13, 0x4a, 0x68, + 0xe7, 0x84, 0xb4, 0xdb, 0xc4, 0x09, 0x7b, 0xe2, 0xfa, 0xd2, 0x77, 0x6d, 0x01, 0xae, 0xba, 0x85, + 0x50, 0x00, 0xbc, 0x4f, 0x1c, 0xc0, 0xc4, 0x95, 0x06, 0xa6, 0xad, 0xf4, 0x08, 0x31, 0x5d, 0xf5, + 0x18, 0x6d, 0xfa, 0x1c, 0xfa, 0x58, 0xd8, 0xbc, 0x03, 0x02, 0x77, 0xed, 0xa0, 0x8b, 0xbb, 0x30, + 0xc4, 0x40, 0x1d, 0xe6, 0x82, 0x2b, 0x4d, 0x4b, 0x5b, 0xf9, 0x88, 0x73, 0x21, 0x29, 0x67, 0x76, + 0xd0, 0x3d, 0x83, 0xa1, 0x11, 0xc7, 0xd5, 0x7f, 0xd0, 0x6f, 0x14, 0x06, 0xdf, 0x94, 0x2f, 0x48, + 0xf9, 0x2f, 0x14, 0x06, 0x4f, 0xaa, 0xf7, 0xd1, 0x9a, 0xac, 0x3e, 0xbd, 0x0f, 0x0c, 0x9e, 0x2d, + 0x0d, 0x4b, 0x45, 0x13, 0x43, 0xbf, 0x36, 0xbe, 0x1d, 0xc3, 0xb3, 0xd5, 0xbf, 0x90, 0x1a, 0x15, + 0x9b, 0x63, 0x2f, 0x4a, 0xf6, 0x2a, 0x85, 0xc1, 0x2c, 0xb9, 0xf4, 0x59, 0x41, 0x9b, 0xd2, 0x9e, + 0xb2, 0xef, 0xf7, 0x88, 0x23, 0x5f, 0x59, 0xbd, 0x0f, 0x7c, 0x34, 0xbb, 0xab, 0xfe, 0x89, 0xb2, + 0xf6, 0x34, 0x84, 0x6d, 0xd7, 0xe5, 0x23, 0x7f, 0x56, 0x67, 0xf0, 0xb2, 0xeb, 0x72, 0xf5, 0x77, + 0x94, 0x09, 0xc2, 0x08, 0x03, 0x1e, 0xf3, 0x62, 0x5b, 0x96, 0xc7, 0xa0, 0x24, 0x1d, 0xa3, 0x0c, + 0x0c, 0x7d, 0x70, 0x04, 0xb8, 0xb8, 0x15, 0x72, 0x2a, 0x87, 0x5f, 0x3a, 0xfc, 0x55, 0x8b, 0xb7, + 0x8a, 0x16, 0x6d, 0x15, 0x6d, 0xb4, 0x55, 0xb4, 0x2a, 0x23, 0xd4, 0x5a, 0x1e, 0xf3, 0x2b, 0x21, + 0xa7, 0xea, 0xbf, 0x68, 0x05, 0xda, 0x6d, 0x70, 0x04, 0xe9, 0x43, 0x9c, 0x20, 0xf5, 0xbd, 0x04, + 0x99, 0x89, 0x20, 0xca, 0xb0, 0xf7, 0x12, 0xad, 0x3f, 0xf9, 0xff, 0x53, 0x77, 0xd0, 0x96, 0xf1, + 0xbc, 0x61, 0x5a, 0xe5, 0x0b, 0xb3, 0x5e, 0xc3, 0x96, 0x51, 0x6e, 0xd6, 0x6b, 0xf8, 0xb2, 0xd6, + 0x6c, 0x18, 0x55, 0xf3, 0xd4, 0x34, 0x4e, 0xb2, 0x09, 0x35, 0x87, 0x32, 0x0d, 0xab, 0x5e, 0x3f, + 0xc5, 0xe7, 0x66, 0xb3, 0x69, 0xd6, 0xfe, 0xcb, 0x2a, 0x53, 0xc8, 0xac, 0x3d, 0x2b, 0xff, 0x6f, + 0x9e, 0x64, 0x93, 0x95, 0xf3, 0x0f, 0x77, 0x05, 0xe5, 0xe6, 0xae, 0xa0, 0x7c, 0xba, 0x2b, 0x28, + 0x6f, 0xee, 0x0b, 0x89, 0x9b, 0xfb, 0x42, 0xe2, 0xe3, 0x7d, 0x21, 0xf1, 0xe2, 0xa8, 0x43, 0x44, + 0x37, 0x6c, 0x69, 0x0e, 0xf3, 0xf4, 0xe8, 0xa1, 0xef, 0x53, 0x10, 0x03, 0xc6, 0xaf, 0xf4, 0xc9, + 0x76, 0x1c, 0xce, 0xee, 0x62, 0xb9, 0x24, 0x5b, 0x3f, 0xc9, 0x2d, 0x79, 0xf4, 0x25, 0x00, 0x00, + 0xff, 0xff, 0x0c, 0xdb, 0x5a, 0x92, 0xaf, 0x05, 0x00, 0x00, } func (m *EventClaimExpired) Marshal() (dAtA []byte, err error) { @@ -700,62 +625,6 @@ func (m *EventApplicationOverserviced) MarshalToSizedBuffer(dAtA []byte) (int, e return len(dAtA) - i, nil } -func (m *EventApplicationReimbursementRequest) 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 *EventApplicationReimbursementRequest) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *EventApplicationReimbursementRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.Amount != nil { - { - size, err := m.Amount.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintEvent(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x22 - } - if len(m.SessionId) > 0 { - i -= len(m.SessionId) - copy(dAtA[i:], m.SessionId) - i = encodeVarintEvent(dAtA, i, uint64(len(m.SessionId))) - i-- - dAtA[i] = 0x1a - } - if len(m.ServiceId) > 0 { - i -= len(m.ServiceId) - copy(dAtA[i:], m.ServiceId) - i = encodeVarintEvent(dAtA, i, uint64(len(m.ServiceId))) - i-- - dAtA[i] = 0x12 - } - if len(m.ApplicationAddr) > 0 { - i -= len(m.ApplicationAddr) - copy(dAtA[i:], m.ApplicationAddr) - i = encodeVarintEvent(dAtA, i, uint64(len(m.ApplicationAddr))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - func encodeVarintEvent(dAtA []byte, offset int, v uint64) int { offset -= sovEvent(v) base := offset @@ -863,31 +732,6 @@ func (m *EventApplicationOverserviced) Size() (n int) { return n } -func (m *EventApplicationReimbursementRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ApplicationAddr) - if l > 0 { - n += 1 + l + sovEvent(uint64(l)) - } - l = len(m.ServiceId) - if l > 0 { - n += 1 + l + sovEvent(uint64(l)) - } - l = len(m.SessionId) - if l > 0 { - n += 1 + l + sovEvent(uint64(l)) - } - if m.Amount != nil { - l = m.Amount.Size() - n += 1 + l + sovEvent(uint64(l)) - } - return n -} - func sovEvent(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -1550,188 +1394,6 @@ func (m *EventApplicationOverserviced) Unmarshal(dAtA []byte) error { } return nil } -func (m *EventApplicationReimbursementRequest) 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 ErrIntOverflowEvent - } - 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: EventApplicationReimbursementRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: EventApplicationReimbursementRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ApplicationAddr", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowEvent - } - 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 ErrInvalidLengthEvent - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthEvent - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ApplicationAddr = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ServiceId", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowEvent - } - 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 ErrInvalidLengthEvent - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthEvent - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ServiceId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field SessionId", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowEvent - } - 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 ErrInvalidLengthEvent - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthEvent - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.SessionId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowEvent - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthEvent - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthEvent - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Amount == nil { - m.Amount = &types1.Coin{} - } - if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipEvent(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthEvent - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} func skipEvent(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 From bbe2366126da7220a96be17804acd4d58976ee11 Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Fri, 23 Aug 2024 11:55:46 -0400 Subject: [PATCH 07/31] WIP --- config.yml | 18 +++ e2e/tests/0_settlement.feature | 24 +++- .../keeper/token_logic_modules_test.go | 126 +++++++++--------- 3 files changed, 99 insertions(+), 69 deletions(-) diff --git a/config.yml b/config.yml index 188eef958..2a945a92a 100644 --- a/config.yml +++ b/config.yml @@ -27,6 +27,10 @@ accounts: mnemonic: "involve clean slab term real human green immune valid swing protect talk silent unique cart few ice era right thunder again drop among bounce" coins: - 300000000upokt + - name: apptiny + mnemonic: "worry pupil rival such jump pitch flame prosper tattoo eternal round receive cube crowd remove afraid garment brand toy nut guitar toy sausage fragile" + coins: + - 1000000upokt # 1 POKT - name: supplier1 mnemonic: "cool industry busy tumble funny relax error state height like board wing goat emerge visual idle never unveil announce hill primary okay spatial frog" coins: @@ -169,6 +173,20 @@ genesis: # `supplier1_stake_config.yaml` so that the stake command causes a state change. amount: "1000068" denom: upokt + - address: pokt1ad28jdap2zfanjd7hpkh984yveney6k9a42man + delegatee_gateway_addresses: [] + service_configs: + - service: + id: anvil + - service: + id: rest + - service: + id: ollama + stake: + # NB: This value should be exactly 1upokt smaller than the value in + # `supplier1_stake_config.yaml` so that the stake command causes a state change. + amount: "1000068" + denom: upokt supplier: supplierList: - owner_address: pokt19a3t4yunp0dlpfjrp7qwnzwlrzd5fzs2gjaaaj diff --git a/e2e/tests/0_settlement.feature b/e2e/tests/0_settlement.feature index b4eaf2441..89ab2527c 100644 --- a/e2e/tests/0_settlement.feature +++ b/e2e/tests/0_settlement.feature @@ -7,30 +7,42 @@ Feature: Tokenomics Namespace - Scenario: Emissions equals burn when a claim is created and a valid proof is submitted and required - # Baseline + Scenario: Mint equals burn when a claim is created and a valid proof is submitted and required Given the user has the pocketd binary installed - # Network preparation + # Network preparation and validation And an account exists for "supplier1" And the "supplier" account for "supplier1" is staked And an account exists for "app1" And the "application" account for "app1" is staked And the service "anvil" registered for application "app1" has a compute units per relay of "1" - # Start servicing + # Start servicing relays When the supplier "supplier1" has serviced a session with "10" relays for service "anvil" for application "app1" # Wait for the Claim & Proof lifecycle And the user should wait for the "proof" module "CreateClaim" Message to be submitted And the user should wait for the "proof" module "SubmitProof" Message to be submitted And the user should wait for the "tokenomics" module "ClaimSettled" end block event to be broadcast - # Validate the results + # Validate that mint equals burn Then the account balance of "supplier1" should be "420" uPOKT "more" than before And the "application" stake of "app1" should be "420" uPOKT "less" than before + Scenario: + Given the user has the pocketd binary installed + # Network preparation + And an account exists for "supplier1" + And the "supplier" account for "supplier1" is staked + And an account exists for "app1" + And the "application" account for "app1" is staked + And the service "anvil" registered for application "app1" has a compute units per relay of "1" + # Start servicing relays + When the supplier "supplier1" has serviced a session with "10" relays for service "anvil" for application "app1" + # Wait for the Claim & Proof lifecycle + And the user should wait for the "tokenomics" module "ClaimSettled" end block event to be broadcast + # TODO_IN_THIS_PR: Add the following test # Scenario: Supplier overservices an application and gets paid for less work than claimed # TODO_ADDTEST: Implement the following scenarios - # Scenario: Emissions equals burn when a claim is created and a valid proof is submitted but not required + # Scenario: Mint equals burn when a claim is created and a valid proof is submitted but not required # Scenario: No emissions or burn when a claim is created and an invalid proof is submitted # Scenario: No emissions or burn when a claim is created and a proof is required but is not submitted # Scenario: No emissions or burn when no claim is created \ No newline at end of file diff --git a/x/tokenomics/keeper/token_logic_modules_test.go b/x/tokenomics/keeper/token_logic_modules_test.go index e842abe59..849146091 100644 --- a/x/tokenomics/keeper/token_logic_modules_test.go +++ b/x/tokenomics/keeper/token_logic_modules_test.go @@ -39,68 +39,7 @@ func init() { // func TestProcessTokenLogicModules_ValidateAppOverServicingEvent(t *testing.T) {...} // func TestProcessTokenLogicModules_ValidateAppReimbursedRequestEvent(t *testing.T) {...} -func TestProcessTokenLogicModules_HandleAppGoingIntoDebt(t *testing.T) { - keepers, ctx := testkeeper.NewTokenomicsModuleKeepers(t, nil) - - // Create a service that can be registered in the application and used in the claims - service := &sharedtypes.Service{ - Id: "svc1", - Name: "svcName1", - ComputeUnitsPerRelay: 1, - OwnerAddress: sample.AccAddress(), - } - keepers.SetService(ctx, *service) - - // Add a new application - appStake := cosmostypes.NewCoin("upokt", math.NewInt(1000000)) - app := apptypes.Application{ - Address: sample.AccAddress(), - Stake: &appStake, - ServiceConfigs: []*sharedtypes.ApplicationServiceConfig{{Service: service}}, - } - keepers.SetApplication(ctx, app) - - // Add a new supplier - supplierOwnerAddress := sample.AccAddress() - supplierStake := cosmostypes.NewCoin("upokt", math.NewInt(1000000)) - supplier := sharedtypes.Supplier{ - OwnerAddress: supplierOwnerAddress, - OperatorAddress: supplierOwnerAddress, - Stake: &supplierStake, - Services: []*sharedtypes.SupplierServiceConfig{ - { - Service: service, - RevShare: []*sharedtypes.ServiceRevenueShare{ - { - Address: supplierOwnerAddress, - RevSharePercentage: 100, - }, - }, - }, - }, - } - keepers.SetSupplier(ctx, supplier) - - // The base claim whose root will be customized for testing purposes - numRelays := appStake.Amount.Uint64() + 1 // More than the app stake - numComputeUnits := numRelays * service.ComputeUnitsPerRelay - claim := prooftypes.Claim{ - SupplierOperatorAddress: supplier.OperatorAddress, - SessionHeader: &sessiontypes.SessionHeader{ - ApplicationAddress: app.Address, - Service: service, - SessionId: "session_id", - SessionStartBlockHeight: 1, - SessionEndBlockHeight: testsession.GetSessionEndHeightWithDefaultParams(1), - }, - RootHash: testproof.SmstRootWithSumAndCount(numComputeUnits, numRelays), - } - - err := keepers.ProcessTokenLogicModules(ctx, &claim) - require.NoError(t, err) -} - -func TestProcessTokenLogicModules_ValidAccounting(t *testing.T) { +func TestProcessTokenLogicModules_ValidateBurnEqualsMintValidAccounting(t *testing.T) { // Create a service that can be registered in the application and used in the claims service := &sharedtypes.Service{ Id: "svc1", @@ -228,7 +167,9 @@ func TestProcessTokenLogicModules_ValidAccounting(t *testing.T) { require.EqualValues(t, supplierModuleStartBalance, supplierModuleEndBalance) } -func TestProcessTokenLogicModules_AppStakeTooLow(t *testing.T) { +func TestProcessTokenLogicModules_HandleAppGoingIntoDebt(t *testing.T) { + keepers, ctx := testkeeper.NewTokenomicsModuleKeepers(t, nil) + // Create a service that can be registered in the application and used in the claims service := &sharedtypes.Service{ Id: "svc1", @@ -236,10 +177,69 @@ func TestProcessTokenLogicModules_AppStakeTooLow(t *testing.T) { ComputeUnitsPerRelay: 1, OwnerAddress: sample.AccAddress(), } + keepers.SetService(ctx, *service) + + // Add a new application + appStake := cosmostypes.NewCoin("upokt", math.NewInt(1000000)) + app := apptypes.Application{ + Address: sample.AccAddress(), + Stake: &appStake, + ServiceConfigs: []*sharedtypes.ApplicationServiceConfig{{Service: service}}, + } + keepers.SetApplication(ctx, app) + // Add a new supplier + supplierOwnerAddress := sample.AccAddress() + supplierStake := cosmostypes.NewCoin("upokt", math.NewInt(1000000)) + supplier := sharedtypes.Supplier{ + OwnerAddress: supplierOwnerAddress, + OperatorAddress: supplierOwnerAddress, + Stake: &supplierStake, + Services: []*sharedtypes.SupplierServiceConfig{ + { + Service: service, + RevShare: []*sharedtypes.ServiceRevenueShare{ + { + Address: supplierOwnerAddress, + RevSharePercentage: 100, + }, + }, + }, + }, + } + keepers.SetSupplier(ctx, supplier) + + // The base claim whose root will be customized for testing purposes + numRelays := appStake.Amount.Uint64() + 1 // More than the app stake + numComputeUnits := numRelays * service.ComputeUnitsPerRelay + claim := prooftypes.Claim{ + SupplierOperatorAddress: supplier.OperatorAddress, + SessionHeader: &sessiontypes.SessionHeader{ + ApplicationAddress: app.Address, + Service: service, + SessionId: "session_id", + SessionStartBlockHeight: 1, + SessionEndBlockHeight: testsession.GetSessionEndHeightWithDefaultParams(1), + }, + RootHash: testproof.SmstRootWithSumAndCount(numComputeUnits, numRelays), + } + + err := keepers.ProcessTokenLogicModules(ctx, &claim) + require.NoError(t, err) +} + +func TestProcessTokenLogicModules_AppStakeTooLow(t *testing.T) { + // Create a service that can be registered in the application and used in the claims + service := &sharedtypes.Service{ + Id: "svc1", + Name: "svcName1", + ComputeUnitsPerRelay: 1, + OwnerAddress: sample.AccAddress(), + } keepers, ctx := testkeeper.NewTokenomicsModuleKeepers(t, nil, testkeeper.WithService(*service)) keepers.SetService(ctx, *service) + // Retrieve the app and supplier module addresses appModuleAddress := authtypes.NewModuleAddress(apptypes.ModuleName).String() supplierModuleAddress := authtypes.NewModuleAddress(suppliertypes.ModuleName).String() From ad70e7071ecbe8fd5cad37168cf04cbee0946002 Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Fri, 23 Aug 2024 15:44:10 -0400 Subject: [PATCH 08/31] Fixed the TestProcessTokenLogicModules_TLMBurnEqualsMintValid test --- testutil/keeper/tokenomics.go | 3 + x/tokenomics/keeper/token_logic_modules.go | 83 ++++--- .../keeper/token_logic_modules_test.go | 208 ++++++++---------- x/tokenomics/types/errors.go | 2 +- x/tokenomics/types/expected_keepers.go | 1 + 5 files changed, 152 insertions(+), 145 deletions(-) diff --git a/testutil/keeper/tokenomics.go b/testutil/keeper/tokenomics.go index 089913a36..6ec0e64df 100644 --- a/testutil/keeper/tokenomics.go +++ b/testutil/keeper/tokenomics.go @@ -186,6 +186,9 @@ func TokenomicsKeeperWithActorAddrs(t testing.TB) ( mockBankKeeper.EXPECT(). SendCoinsFromModuleToAccount(gomock.Any(), tokenomicstypes.ModuleName, gomock.Any(), gomock.Any()). AnyTimes() + mockBankKeeper.EXPECT(). + SendCoinsFromModuleToModule(gomock.Any(), tokenomicstypes.ModuleName, suppliertypes.ModuleName, gomock.Any()). + AnyTimes() // Mock the account keeper mockAccountKeeper := mocks.NewMockAccountKeeper(ctrl) diff --git a/x/tokenomics/keeper/token_logic_modules.go b/x/tokenomics/keeper/token_logic_modules.go index 3db0c9b41..33f24e618 100644 --- a/x/tokenomics/keeper/token_logic_modules.go +++ b/x/tokenomics/keeper/token_logic_modules.go @@ -24,11 +24,13 @@ import ( tokenomictypes "github.com/pokt-network/poktroll/x/tokenomics/types" ) -const ( +var ( // Governance parameters for the TLMGlobalMint module // TODO_UPNEXT(@olshansk, #732): Make this a governance parameter and give it a non-zero value + tests. - MintPerClaimGlobalInflation = 0.0000000 + MintPerClaimGlobalInflation = 0.1 +) +const ( // TODO_BETA(@bryanchriswhite): Make all of the governance params MintAllocationDAO = 0.1 MintAllocationProposer = 0.05 @@ -333,18 +335,23 @@ func (k Keeper) TokenLogicModuleGlobalMint( ) error { logger := k.Logger().With("method", "TokenLogicModuleGlobalMint") + if MintPerClaimGlobalInflation == 0 { + logger.Warn("global inflation is set to zero. Skipping Global Mint TLM.") + return nil + } + // Determine how much new uPOKT to mint based on global inflation - newMintCoins, newMintAmtFloat := calculateGlobalPerClaimMintInflationFromSettlementAmount(settlementCoin) + newMintCoin, newMintAmtFloat := calculateGlobalPerClaimMintInflationFromSettlementAmount(settlementCoin) // Mint new uPOKT to the tokenomics module account - if err := k.bankKeeper.MintCoins(ctx, tokenomictypes.ModuleName, newMintCoins); err != nil { + if err := k.bankKeeper.MintCoins(ctx, tokenomictypes.ModuleName, sdk.NewCoins(newMintCoin)); err != nil { return tokenomicstypes.ErrTokenomicsModuleMintFailed.Wrapf( - "minting %s to the tokenomics module account: %v", newMintCoins, err) + "minting %s to the tokenomics module account: %v", newMintCoin, err) } - logger.Info(fmt.Sprintf("minted (%v) coins in the tokenomics module", newMintCoins)) + logger.Info(fmt.Sprintf("minted (%v) coins in the tokenomics module", newMintCoin)) // Send a portion of the rewards to the application - appCoin, err := k.sendRewardsToAccount(ctx, application.Address, newMintAmtFloat, MintAllocationApplication) + appCoin, err := k.sendRewardsToAccount(ctx, tokenomictypes.ModuleName, application.Address, newMintAmtFloat, MintAllocationApplication) if err != nil { return tokenomictypes.ErrTokenomicsSendingMintRewards.Wrapf("sending rewards to application: %v", err) } @@ -353,6 +360,15 @@ func (k Keeper) TokenLogicModuleGlobalMint( // Send a portion of the rewards to the supplier shareholders. supplierCoinsToShareAmt := calculateAllocationAmount(newMintAmtFloat, MintAllocationSupplier) supplierCoin := cosmostypes.NewCoin(volatile.DenomuPOKT, math.NewInt(supplierCoinsToShareAmt)) + // Send funds from the tokenomics module to the supplier module account + if err = k.bankKeeper.SendCoinsFromModuleToModule(ctx, tokenomicstypes.ModuleName, suppliertypes.ModuleName, sdk.NewCoins(supplierCoin)); err != nil { + return tokenomicstypes.ErrTokenomicsSupplierModuleSendFailed.Wrapf( + "sending %s from the tokenomics module to the supplier module account: %v", + supplierCoin, + err, + ) + } + // Distribute the rewards from within the supplier's module account. if err = k.distributeSupplierRewardsToShareHolders(ctx, supplier.OperatorAddress, service.Id, uint64(supplierCoinsToShareAmt)); err != nil { return tokenomicstypes.ErrTokenomicsSupplierModuleMintFailed.Wrapf( "distributing rewards to supplier with operator address %s shareholders: %v", @@ -364,14 +380,14 @@ func (k Keeper) TokenLogicModuleGlobalMint( logger.Debug(fmt.Sprintf("sent (%v) newley minted coins from the tokenomics module to the supplier with address %q", supplierCoin, supplier.OperatorAddress)) // Send a portion of the rewards to the DAO - daoCoin, err := k.sendRewardsToAccount(ctx, k.GetAuthority(), newMintAmtFloat, MintAllocationDAO) + daoCoin, err := k.sendRewardsToAccount(ctx, tokenomictypes.ModuleName, k.GetAuthority(), newMintAmtFloat, MintAllocationDAO) if err != nil { return tokenomictypes.ErrTokenomicsSendingMintRewards.Wrapf("sending rewards to DAO: %v", err) } logger.Debug(fmt.Sprintf("sent (%v) newley minted coins from the tokenomics module to the DAO with address %q", daoCoin, k.GetAuthority())) // Send a portion of the rewards to the source owner - serviceCoin, err := k.sendRewardsToAccount(ctx, service.OwnerAddress, newMintAmtFloat, MintAllocationSourceOwner) + serviceCoin, err := k.sendRewardsToAccount(ctx, tokenomictypes.ModuleName, service.OwnerAddress, newMintAmtFloat, MintAllocationSourceOwner) if err != nil { return tokenomictypes.ErrTokenomicsSendingMintRewards.Wrapf("sending rewards to source owner: %v", err) } @@ -379,18 +395,30 @@ func (k Keeper) TokenLogicModuleGlobalMint( // Send a portion of the rewards to the block proposer proposerAddr := cosmostypes.AccAddress(sdk.UnwrapSDKContext(ctx).BlockHeader().ProposerAddress).String() - proposerCoin, err := k.sendRewardsToAccount(ctx, proposerAddr, newMintAmtFloat, MintAllocationProposer) + proposerCoin, err := k.sendRewardsToAccount(ctx, tokenomictypes.ModuleName, proposerAddr, newMintAmtFloat, MintAllocationProposer) if err != nil { return tokenomictypes.ErrTokenomicsSendingMintRewards.Wrapf("sending rewards to proposer: %v", err) } logger.Debug(fmt.Sprintf("sent (%v) newley minted coins from the tokenomics module to the proposer with address %q", proposerCoin, proposerAddr)) // Check and log the total amount of coins distributed - totalDistributedCoins := appCoin.Add(supplierCoin).Add(*daoCoin).Add(*serviceCoin).Add(*proposerCoin) - if totalDistributedCoins.Amount.BigInt().Cmp(newMintCoins[0].Amount.BigInt()) != 0 { - return tokenomictypes.ErrTokenomicsAmountMismatch.Wrapf("the total distributed coins (%v) do not equal the settlement coins (%v). Likely floating point arithmetic.", totalDistributedCoins, settlementCoin.Amount.BigInt()) - } - logger.Info(fmt.Sprintf("distributed (%v) coins to the application, supplier, DAO, source owner, and proposer", totalDistributedCoins)) + totalMintDistributedCoin := appCoin.Add(supplierCoin).Add(*daoCoin).Add(*serviceCoin).Add(*proposerCoin) + coinDifference := new(big.Int).Sub(totalMintDistributedCoin.Amount.BigInt(), newMintCoin.Amount.BigInt()) + coinDifference = coinDifference.Abs(coinDifference) + percentDifference := new(big.Float).Quo(new(big.Float).SetInt(coinDifference), new(big.Float).SetInt(newMintCoin.Amount.BigInt())) + if percentDifference.Cmp(big.NewFloat(0.01)) > 0 { + return tokenomictypes.ErrTokenomicsAmountMismatchTooLarge.Wrapf( + "the total distributed coins (%v) do not equal the amount of new minted coins (%v). Likely floating point arithmetic.\n"+ + "appCoin: %v, supplierCoin: %v, daoCoin: %v, serviceCoin: %v, proposerCoin: %v", + totalMintDistributedCoin, newMintCoin, + appCoin, supplierCoin, daoCoin, serviceCoin, proposerCoin) + } else if coinDifference.Cmp(big.NewInt(0)) > 0 { + logger.Warn(fmt.Sprintf("Floating point arithmetic led to a discrepancy of %v (%f) between the total distributed coins (%v) and the amount of new minted coins (%v).\n"+ + "appCoin: %v, supplierCoin: %v, daoCoin: %v, serviceCoin: %v, proposerCoin: %v", + coinDifference, percentDifference, totalMintDistributedCoin, newMintCoin, + appCoin, supplierCoin, daoCoin, serviceCoin, proposerCoin)) + } + logger.Info(fmt.Sprintf("distributed (%v) coins to the application, supplier, DAO, source owner, and proposer", totalMintDistributedCoin)) return nil } @@ -399,13 +427,14 @@ func (k Keeper) TokenLogicModuleGlobalMint( // tokenomics module account to the specified address. func (k Keeper) sendRewardsToAccount( ctx context.Context, - addr string, + srcModule string, + destAdr string, settlementAmtFloat *big.Float, allocation float64, ) (*sdk.Coin, error) { logger := k.Logger().With("method", "mintRewardsToAccount") - accountAddr, err := cosmostypes.AccAddressFromBech32(addr) + accountAddr, err := cosmostypes.AccAddressFromBech32(destAdr) if err != nil { return nil, err } @@ -413,11 +442,11 @@ func (k Keeper) sendRewardsToAccount( coinsToAccAmt := calculateAllocationAmount(settlementAmtFloat, allocation) coinToAcc := cosmostypes.NewCoin(volatile.DenomuPOKT, math.NewInt(coinsToAccAmt)) if err := k.bankKeeper.SendCoinsFromModuleToAccount( - ctx, suppliertypes.ModuleName, accountAddr, sdk.NewCoins(coinToAcc), + ctx, srcModule, accountAddr, sdk.NewCoins(coinToAcc), ); err != nil { return nil, err } - logger.Info(fmt.Sprintf("sent (%v) coins from the tokenomics module to the account with address %q", coinToAcc, addr)) + logger.Info(fmt.Sprintf("sent (%v) coins from the tokenomics module to the account with address %q", coinToAcc, destAdr)) return &coinToAcc, nil } @@ -504,17 +533,17 @@ func (k Keeper) numRelaysToCoin( // shareholders based on the rev share percentage of the supplier service config. func (k Keeper) distributeSupplierRewardsToShareHolders( ctx context.Context, - supplierAddr string, + supplierOperatorAddr string, serviceId string, amountToDistribute uint64, ) error { logger := k.Logger().With("method", "distributeSupplierRewardsToShareHolders") - supplier, supplierFound := k.supplierKeeper.GetSupplier(ctx, supplierAddr) + supplier, supplierFound := k.supplierKeeper.GetSupplier(ctx, supplierOperatorAddr) if !supplierFound { return tokenomicstypes.ErrTokenomicsSupplierRevShareFailed.Wrapf( "supplier with address %q not found", - supplierAddr, + supplierOperatorAddr, ) } @@ -552,10 +581,10 @@ func (k Keeper) distributeSupplierRewardsToShareHolders( return err } - logger.Info(fmt.Sprintf("sent %s from the supplier module to the supplier shareholder with address %q", shareAmountCoin, supplierAddr)) + logger.Info(fmt.Sprintf("sent %s from the supplier module to the supplier shareholder with address %q", shareAmountCoin, supplierOperatorAddr)) } - logger.Info(fmt.Sprintf("distributed %d uPOKT to supplier %q shareholders", amountToDistribute, supplierAddr)) + logger.Info(fmt.Sprintf("distributed %d uPOKT to supplier %q shareholders", amountToDistribute, supplierOperatorAddr)) return nil } @@ -563,14 +592,14 @@ func (k Keeper) distributeSupplierRewardsToShareHolders( // calculateGlobalPerClaimMintInflationFromSettlementAmount calculates the amount // of uPOKT to mint based on the global per claim inflation rate as a function of // the settlement amount for a particular claim(s) or session(s). -func calculateGlobalPerClaimMintInflationFromSettlementAmount(settlementCoin sdk.Coin) (sdk.Coins, *big.Float) { +func calculateGlobalPerClaimMintInflationFromSettlementAmount(settlementCoin sdk.Coin) (sdk.Coin, *big.Float) { // Determine how much new uPOKT to mint based on global per claim inflation. // TODO_MAINNET: Consider using fixed point arithmetic for deterministic results. settlementAmtFloat := new(big.Float).SetUint64(settlementCoin.Amount.Uint64()) newMintAmtFloat := new(big.Float).Mul(settlementAmtFloat, big.NewFloat(MintPerClaimGlobalInflation)) newMintAmtInt, _ := newMintAmtFloat.Int64() - mintAmtCoins := sdk.NewCoins(cosmostypes.NewCoin(volatile.DenomuPOKT, math.NewInt(newMintAmtInt))) - return mintAmtCoins, newMintAmtFloat + mintAmtCoin := cosmostypes.NewCoin(volatile.DenomuPOKT, math.NewInt(newMintAmtInt)) + return mintAmtCoin, newMintAmtFloat } // calculateAllocationAmount does big float arithmetic to determine the absolute diff --git a/x/tokenomics/keeper/token_logic_modules_test.go b/x/tokenomics/keeper/token_logic_modules_test.go index 849146091..e2db9c5c3 100644 --- a/x/tokenomics/keeper/token_logic_modules_test.go +++ b/x/tokenomics/keeper/token_logic_modules_test.go @@ -9,11 +9,13 @@ import ( "cosmossdk.io/math" "github.com/cometbft/cometbft/libs/json" cosmostypes "github.com/cosmos/cosmos-sdk/types" + sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/pokt-network/smt" "github.com/stretchr/testify/require" + "github.com/pokt-network/poktroll/app/volatile" "github.com/pokt-network/poktroll/cmd/poktrolld/cmd" "github.com/pokt-network/poktroll/pkg/crypto/protocol" testkeeper "github.com/pokt-network/poktroll/testutil/keeper" @@ -22,10 +24,11 @@ import ( testsession "github.com/pokt-network/poktroll/testutil/session" apptypes "github.com/pokt-network/poktroll/x/application/types" prooftypes "github.com/pokt-network/poktroll/x/proof/types" + sessionkeeper "github.com/pokt-network/poktroll/x/session/keeper" sessiontypes "github.com/pokt-network/poktroll/x/session/types" sharedtypes "github.com/pokt-network/poktroll/x/shared/types" suppliertypes "github.com/pokt-network/poktroll/x/supplier/types" - "github.com/pokt-network/poktroll/x/tokenomics/keeper" + tokenomicskeeper "github.com/pokt-network/poktroll/x/tokenomics/keeper" tokenomicstypes "github.com/pokt-network/poktroll/x/tokenomics/types" ) @@ -39,31 +42,49 @@ func init() { // func TestProcessTokenLogicModules_ValidateAppOverServicingEvent(t *testing.T) {...} // func TestProcessTokenLogicModules_ValidateAppReimbursedRequestEvent(t *testing.T) {...} -func TestProcessTokenLogicModules_ValidateBurnEqualsMintValidAccounting(t *testing.T) { +func TestProcessTokenLogicModules_TLMBurnEqualsMintValid(t *testing.T) { + // Test Parameters + appInitialStake := math.NewInt(1000000) + supplierInitialStake := math.NewInt(1000000) + supplierRevShareRatios := []float32{12.5, 37.5, 50} + globalComputeUnitsToTokensMultiplier := uint64(1) + serviceComputeUnitsPerRelay := uint64(1) + numRelays := uint64(1000) + + // Ensure the claim is within relay mining bounds + numTokensClaimed := int64(numRelays * serviceComputeUnitsPerRelay * globalComputeUnitsToTokensMultiplier) + maxClaimableAmount := appInitialStake.Quo(math.NewInt(sessionkeeper.NumSupplierPerSession)) + require.GreaterOrEqual(t, maxClaimableAmount.Int64(), numTokensClaimed) + // Create a service that can be registered in the application and used in the claims service := &sharedtypes.Service{ Id: "svc1", Name: "svcName1", - ComputeUnitsPerRelay: 1, + ComputeUnitsPerRelay: serviceComputeUnitsPerRelay, OwnerAddress: sample.AccAddress(), } - keepers, ctx := testkeeper.NewTokenomicsModuleKeepers(t, nil, testkeeper.WithService(*service)) keepers.SetService(ctx, *service) + // Retrieve the app and supplier module addresses appModuleAddress := authtypes.NewModuleAddress(apptypes.ModuleName).String() supplierModuleAddress := authtypes.NewModuleAddress(suppliertypes.ModuleName).String() - // Set compute_units_to_tokens_multiplier to 1 to simplify expectation calculations. + // Set compute_units_to_tokens_multiplier to simplify expectation calculations. err := keepers.Keeper.SetParams(ctx, tokenomicstypes.Params{ - ComputeUnitsToTokensMultiplier: 1, + ComputeUnitsToTokensMultiplier: globalComputeUnitsToTokensMultiplier, }) require.NoError(t, err) + // TODO_TECHDEBT: Setting inflation to zero so we are testing the BurnEqualsMint logic exclusively. + // Once it is a governance param, update it using the keeper above. + prevInflationValue := tokenomicskeeper.MintPerClaimGlobalInflation + tokenomicskeeper.MintPerClaimGlobalInflation = 0 + t.Cleanup(func() { + tokenomicskeeper.MintPerClaimGlobalInflation = prevInflationValue + }) // Add a new application with non-zero app stake end balance to assert against. - appStake := cosmostypes.NewCoin("upokt", math.NewInt(1000000)) - expectedAppEndStakeAmount := cosmostypes.NewCoin("upokt", math.NewInt(420)) - expectedAppBurn := appStake.Sub(expectedAppEndStakeAmount) + appStake := cosmostypes.NewCoin(volatile.DenomuPOKT, appInitialStake) app := apptypes.Application{ Address: sample.AccAddress(), Stake: &appStake, @@ -71,55 +92,38 @@ func TestProcessTokenLogicModules_ValidateBurnEqualsMintValidAccounting(t *testi } keepers.SetApplication(ctx, app) - shareRatios := []float32{12.5, 37.5, 50} - revShares := make([]*sharedtypes.ServiceRevenueShare, len(shareRatios)) - for i := range revShares { + // Determine the expected app end stake amount and the expected app burn + expectedAppBurn := math.NewInt(numTokensClaimed) + expectedAppEndStakeAmount := appInitialStake.Sub(expectedAppBurn) + + // Prepare the supplier revenue shares + supplierRevShares := make([]*sharedtypes.ServiceRevenueShare, len(supplierRevShareRatios)) + for i := range supplierRevShares { shareHolderAddress := sample.AccAddress() - revShares[i] = &sharedtypes.ServiceRevenueShare{ + supplierRevShares[i] = &sharedtypes.ServiceRevenueShare{ Address: shareHolderAddress, - RevSharePercentage: shareRatios[i], + RevSharePercentage: supplierRevShareRatios[i], } } // Add a new supplier. - supplierStake := cosmostypes.NewCoin("upokt", math.NewInt(1000000)) + supplierStake := cosmostypes.NewCoin(volatile.DenomuPOKT, supplierInitialStake) supplier := sharedtypes.Supplier{ // Make the first shareholder the supplier itself. - OwnerAddress: revShares[0].Address, - OperatorAddress: revShares[0].Address, + OwnerAddress: supplierRevShares[0].Address, + OperatorAddress: supplierRevShares[0].Address, Stake: &supplierStake, - Services: []*sharedtypes.SupplierServiceConfig{ - { - Service: service, - RevShare: revShares, - }, - }, + Services: []*sharedtypes.SupplierServiceConfig{{Service: service, RevShare: supplierRevShares}}, } keepers.SetSupplier(ctx, supplier) - // Query application balance prior to the accounting. + // Query the account and module start balances appStartBalance := getBalance(t, ctx, keepers, app.GetAddress()) - // Query application module balance prior to the accounting. appModuleStartBalance := getBalance(t, ctx, keepers, appModuleAddress) - - // Query supplier module balance prior to the accounting. supplierModuleStartBalance := getBalance(t, ctx, keepers, supplierModuleAddress) - // Assumes ComputeUnitToTokenMultiplier is 1 - numComputeUnits := expectedAppBurn.Amount.Uint64() - numRelays := numComputeUnits / service.ComputeUnitsPerRelay - // The base claim whose root will be customized for testing purposes - claim := prooftypes.Claim{ - SupplierOperatorAddress: supplier.OperatorAddress, - SessionHeader: &sessiontypes.SessionHeader{ - ApplicationAddress: app.Address, - Service: service, - SessionId: "session_id", - SessionStartBlockHeight: 1, - SessionEndBlockHeight: testsession.GetSessionEndHeightWithDefaultParams(1), - }, - RootHash: testproof.SmstRootWithSumAndCount(numComputeUnits, numRelays), - } + // Prepare the claim for which the supplier did work for the application + claim := prepareClaim(numRelays, service, &app, &supplier) // Process the token logic modules err = keepers.ProcessTokenLogicModules(ctx, &claim) @@ -132,29 +136,16 @@ func TestProcessTokenLogicModules_ValidateBurnEqualsMintValidAccounting(t *testi // Assert that `applicationAddress` staked balance has decreased by the appropriate amount app, appIsFound := keepers.GetApplication(ctx, app.GetAddress()) require.True(t, appIsFound) - require.Equal(t, &expectedAppEndStakeAmount, app.GetStake()) + require.Equal(t, expectedAppEndStakeAmount, app.GetStake().Amount) - // Assert that `apptypes.ModuleName` account module balance is *decreased* by the appropriate amount + // Assert that app module balance is *decreased* by the appropriate amount // NB: The application module account burns the amount of uPOKT that was held in escrow // on behalf of the applications which were serviced in a given session. + expectedAppModuleEndBalance := appModuleStartBalance.Sub(sdk.NewCoin(volatile.DenomuPOKT, expectedAppBurn)) appModuleEndBalance := getBalance(t, ctx, keepers, appModuleAddress) - expectedAppModuleEndBalance := appModuleStartBalance.Sub(expectedAppBurn) require.NotNil(t, appModuleEndBalance) require.EqualValues(t, &expectedAppModuleEndBalance, appModuleEndBalance) - // Assert that the supplier shareholders account balances have *increased* by - // the appropriate amount. - mintAmountInt := expectedAppBurn.Amount.Uint64() - shareAmounts := keeper.GetShareAmountMap(supplier.Services[0].RevShare, mintAmountInt) - for shareHolder, expectedShareAmount := range shareAmounts { - shareHolderBalance := getBalance(t, ctx, keepers, shareHolder) - - require.Equal(t, - int64(expectedShareAmount), - shareHolderBalance.Amount.Int64(), - ) - } - // Assert that `supplierOperatorAddress` staked balance is *unchanged* supplier, supplierIsFound := keepers.GetSupplier(ctx, supplier.GetOperatorAddress()) require.True(t, supplierIsFound) @@ -165,70 +156,24 @@ func TestProcessTokenLogicModules_ValidateBurnEqualsMintValidAccounting(t *testi // distributed to the supplier accounts which provided service in a given session. supplierModuleEndBalance := getBalance(t, ctx, keepers, supplierModuleAddress) require.EqualValues(t, supplierModuleStartBalance, supplierModuleEndBalance) -} - -func TestProcessTokenLogicModules_HandleAppGoingIntoDebt(t *testing.T) { - keepers, ctx := testkeeper.NewTokenomicsModuleKeepers(t, nil) - - // Create a service that can be registered in the application and used in the claims - service := &sharedtypes.Service{ - Id: "svc1", - Name: "svcName1", - ComputeUnitsPerRelay: 1, - OwnerAddress: sample.AccAddress(), - } - keepers.SetService(ctx, *service) - - // Add a new application - appStake := cosmostypes.NewCoin("upokt", math.NewInt(1000000)) - app := apptypes.Application{ - Address: sample.AccAddress(), - Stake: &appStake, - ServiceConfigs: []*sharedtypes.ApplicationServiceConfig{{Service: service}}, - } - keepers.SetApplication(ctx, app) - // Add a new supplier - supplierOwnerAddress := sample.AccAddress() - supplierStake := cosmostypes.NewCoin("upokt", math.NewInt(1000000)) - supplier := sharedtypes.Supplier{ - OwnerAddress: supplierOwnerAddress, - OperatorAddress: supplierOwnerAddress, - Stake: &supplierStake, - Services: []*sharedtypes.SupplierServiceConfig{ - { - Service: service, - RevShare: []*sharedtypes.ServiceRevenueShare{ - { - Address: supplierOwnerAddress, - RevSharePercentage: 100, - }, - }, - }, - }, - } - keepers.SetSupplier(ctx, supplier) - - // The base claim whose root will be customized for testing purposes - numRelays := appStake.Amount.Uint64() + 1 // More than the app stake - numComputeUnits := numRelays * service.ComputeUnitsPerRelay - claim := prooftypes.Claim{ - SupplierOperatorAddress: supplier.OperatorAddress, - SessionHeader: &sessiontypes.SessionHeader{ - ApplicationAddress: app.Address, - Service: service, - SessionId: "session_id", - SessionStartBlockHeight: 1, - SessionEndBlockHeight: testsession.GetSessionEndHeightWithDefaultParams(1), - }, - RootHash: testproof.SmstRootWithSumAndCount(numComputeUnits, numRelays), + // Assert that the supplier shareholders account balances have *increased* by + // the appropriate amount w.r.t token distribution. + shareAmounts := tokenomicskeeper.GetShareAmountMap(supplierRevShares, expectedAppBurn.Uint64()) + for shareHolderAddr, expectedShareAmount := range shareAmounts { + shareHolderBalance := getBalance(t, ctx, keepers, shareHolderAddr) + require.Equal(t, int64(expectedShareAmount), shareHolderBalance.Amount.Int64()) } - - err := keepers.ProcessTokenLogicModules(ctx, &claim) - require.NoError(t, err) } func TestProcessTokenLogicModules_AppStakeTooLow(t *testing.T) { + // Test Parameters + // appInitialStake := math.NewInt(1000000) + // appEndStake := math.NewInt(420) + // supplierInitialStake := math.NewInt(1000000) + // supplierRevShareRatios := []float32{12.5, 37.5, 50} + // computeUnitsToTokensMultiplier := uint64(1) + // Create a service that can be registered in the application and used in the claims service := &sharedtypes.Service{ Id: "svc1", @@ -346,6 +291,14 @@ func TestProcessTokenLogicModules_AppStakeTooLow(t *testing.T) { require.EqualValues(t, supplierModuleStartBalance, supplierModuleEndBalance) // Check that the expected burn >> effective burn because application is overserviced + + // events := sdkCtx.EventManager().Events() + // relayMiningEvents := testutilevents.FilterEvents[*tokenomicstypes.EventRelayMiningDifficultyUpdated](t, + // events, "poktroll.tokenomics.EventRelayMiningDifficultyUpdated") + // require.Len(t, relayMiningEvents, 1, "unexpected number of relay mining difficulty updated events") + // relayMiningEvent := relayMiningEvents[0] + // require.Equal(t, "svc1", relayMiningEvent.ServiceId) + events := cosmostypes.UnwrapSDKContext(ctx).EventManager().Events() appAddrAttribute, _ := events.GetAttributes("application_addr") expectedBurnAttribute, _ := events.GetAttributes("expected_burn") @@ -576,6 +529,27 @@ func TestProcessTokenLogicModules_InvalidClaim(t *testing.T) { } } +func prepareClaim( + numRelays uint64, + service *sharedtypes.Service, + app *apptypes.Application, + supplier *sharedtypes.Supplier, +) prooftypes.Claim { + numComputeUnits := numRelays * service.ComputeUnitsPerRelay + return prooftypes.Claim{ + SupplierOperatorAddress: supplier.OperatorAddress, + SessionHeader: &sessiontypes.SessionHeader{ + ApplicationAddress: app.Address, + Service: service, + SessionId: "session_id", + SessionStartBlockHeight: 1, + SessionEndBlockHeight: testsession.GetSessionEndHeightWithDefaultParams(1), + }, + RootHash: testproof.SmstRootWithSumAndCount(numComputeUnits, numRelays), + } + +} + func getBalance( t *testing.T, ctx context.Context, diff --git a/x/tokenomics/types/errors.go b/x/tokenomics/types/errors.go index 24a16cd1b..018c44601 100644 --- a/x/tokenomics/types/errors.go +++ b/x/tokenomics/types/errors.go @@ -33,5 +33,5 @@ var ( ErrTokenomicsSupplierOwnerAddressInvalid = sdkerrors.Register(ModuleName, 1124, "the supplier owner address in the claim is not a valid bech32 address") ErrTokenomicsSupplierRevShareFailed = sdkerrors.Register(ModuleName, 1125, "failed to send rev share to supplier shareholders") ErrTokenomicsApplicationReimbursementRequestFailed = sdkerrors.Register(ModuleName, 1126, "failed to send application reimbursement request event") - ErrTokenomicsAmountMismatch = sdkerrors.Register(ModuleName, 1127, "an unexpected amount mismatch occurred") + ErrTokenomicsAmountMismatchTooLarge = sdkerrors.Register(ModuleName, 1127, "an unexpected amount mismatch occurred") ) diff --git a/x/tokenomics/types/expected_keepers.go b/x/tokenomics/types/expected_keepers.go index a267cbb18..b6e07314a 100644 --- a/x/tokenomics/types/expected_keepers.go +++ b/x/tokenomics/types/expected_keepers.go @@ -35,6 +35,7 @@ type BankKeeper interface { // than "delegate" funds from one account to another which is more closely // linked to staking. SendCoinsFromModuleToAccount(ctx context.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error + SendCoinsFromModuleToModule(ctx context.Context, senderModule, recipientModule string, amt sdk.Coins) error Balance(context.Context, *banktypes.QueryBalanceRequest) (*banktypes.QueryBalanceResponse, error) } From b02ef24676b3eb145a6520e077ab619e8e21541b Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Fri, 23 Aug 2024 22:23:30 -0400 Subject: [PATCH 09/31] WIP --- .../keeper/token_logic_modules_test.go | 170 ++++++++++-------- 1 file changed, 91 insertions(+), 79 deletions(-) diff --git a/x/tokenomics/keeper/token_logic_modules_test.go b/x/tokenomics/keeper/token_logic_modules_test.go index e2db9c5c3..4bae90d8e 100644 --- a/x/tokenomics/keeper/token_logic_modules_test.go +++ b/x/tokenomics/keeper/token_logic_modules_test.go @@ -18,6 +18,7 @@ import ( "github.com/pokt-network/poktroll/app/volatile" "github.com/pokt-network/poktroll/cmd/poktrolld/cmd" "github.com/pokt-network/poktroll/pkg/crypto/protocol" + testutilevents "github.com/pokt-network/poktroll/testutil/events" testkeeper "github.com/pokt-network/poktroll/testutil/keeper" testproof "github.com/pokt-network/poktroll/testutil/proof" "github.com/pokt-network/poktroll/testutil/sample" @@ -49,12 +50,12 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMintValid(t *testing.T) { supplierRevShareRatios := []float32{12.5, 37.5, 50} globalComputeUnitsToTokensMultiplier := uint64(1) serviceComputeUnitsPerRelay := uint64(1) - numRelays := uint64(1000) + numRelays := uint64(1000) // By supplier for application in this session // Ensure the claim is within relay mining bounds numTokensClaimed := int64(numRelays * serviceComputeUnitsPerRelay * globalComputeUnitsToTokensMultiplier) - maxClaimableAmount := appInitialStake.Quo(math.NewInt(sessionkeeper.NumSupplierPerSession)) - require.GreaterOrEqual(t, maxClaimableAmount.Int64(), numTokensClaimed) + maxClaimableAmountPerSupplier := appInitialStake.Quo(math.NewInt(sessionkeeper.NumSupplierPerSession)) + require.GreaterOrEqual(t, maxClaimableAmountPerSupplier.Int64(), numTokensClaimed) // Create a service that can be registered in the application and used in the claims service := &sharedtypes.Service{ @@ -92,10 +93,6 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMintValid(t *testing.T) { } keepers.SetApplication(ctx, app) - // Determine the expected app end stake amount and the expected app burn - expectedAppBurn := math.NewInt(numTokensClaimed) - expectedAppEndStakeAmount := appInitialStake.Sub(expectedAppBurn) - // Prepare the supplier revenue shares supplierRevShares := make([]*sharedtypes.ServiceRevenueShare, len(supplierRevShareRatios)) for i := range supplierRevShares { @@ -133,10 +130,15 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMintValid(t *testing.T) { appEndBalance := getBalance(t, ctx, keepers, app.GetAddress()) require.EqualValues(t, appStartBalance, appEndBalance) + // Determine the expected app end stake amount and the expected app burn + expectedAppBurn := math.NewInt(numTokensClaimed) + expectedAppEndStakeAmount := appInitialStake.Sub(expectedAppBurn) + // Assert that `applicationAddress` staked balance has decreased by the appropriate amount app, appIsFound := keepers.GetApplication(ctx, app.GetAddress()) + actualAppEndStakeAmount := app.GetStake().Amount require.True(t, appIsFound) - require.Equal(t, expectedAppEndStakeAmount, app.GetStake().Amount) + require.Equal(t, expectedAppEndStakeAmount, actualAppEndStakeAmount) // Assert that app module balance is *decreased* by the appropriate amount // NB: The application module account burns the amount of uPOKT that was held in escrow @@ -166,19 +168,32 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMintValid(t *testing.T) { } } -func TestProcessTokenLogicModules_AppStakeTooLow(t *testing.T) { +// DEV_NOTE: Most of the setup here is a copy-paste of TLMBurnEqualsMintValid +// except that the application stake is calculated to explicitly be too low to +// handle all the relays completed. +func TestProcessTokenLogicModules_TLMBurnEqualsMintInvalid_SupplierExceedsMaxClaimableAmount(t *testing.T) { // Test Parameters - // appInitialStake := math.NewInt(1000000) - // appEndStake := math.NewInt(420) - // supplierInitialStake := math.NewInt(1000000) - // supplierRevShareRatios := []float32{12.5, 37.5, 50} - // computeUnitsToTokensMultiplier := uint64(1) + globalComputeUnitsToTokensMultiplier := uint64(1) + serviceComputeUnitsPerRelay := uint64(1) + numRelays := uint64(1000) // By a single supplier for application in this session + supplierInitialStake := math.NewInt(1000000) + supplierRevShareRatios := []float32{12.5, 37.5, 50} + + // Set up the relays to exceed the max claimable amount + // Determine the max a supplier can claim + maxClaimableAmountPerSupplier := int64(numRelays * serviceComputeUnitsPerRelay * globalComputeUnitsToTokensMultiplier) + // Figure out what the app's initial stake should be to cover the max claimable amount + appInitialStake := math.NewInt(maxClaimableAmountPerSupplier*sessionkeeper.NumSupplierPerSession + 1) + // Increase the number of relay such that the supplier did "free work" and would + // be able to claim more than the max claimable amount. + numRelays *= 5 + numTokensClaimed := int64(numRelays * serviceComputeUnitsPerRelay * globalComputeUnitsToTokensMultiplier) // Create a service that can be registered in the application and used in the claims service := &sharedtypes.Service{ Id: "svc1", Name: "svcName1", - ComputeUnitsPerRelay: 1, + ComputeUnitsPerRelay: serviceComputeUnitsPerRelay, OwnerAddress: sample.AccAddress(), } keepers, ctx := testkeeper.NewTokenomicsModuleKeepers(t, nil, testkeeper.WithService(*service)) @@ -188,16 +203,21 @@ func TestProcessTokenLogicModules_AppStakeTooLow(t *testing.T) { appModuleAddress := authtypes.NewModuleAddress(apptypes.ModuleName).String() supplierModuleAddress := authtypes.NewModuleAddress(suppliertypes.ModuleName).String() - // Set compute_units_to_tokens_multiplier to 1 to simplify expectation calculations. + // Set compute_units_to_tokens_multiplier to simplify expectation calculations. err := keepers.Keeper.SetParams(ctx, tokenomicstypes.Params{ - ComputeUnitsToTokensMultiplier: 1, + ComputeUnitsToTokensMultiplier: globalComputeUnitsToTokensMultiplier, }) require.NoError(t, err) + // TODO_TECHDEBT: Setting inflation to zero so we are testing the BurnEqualsMint logic exclusively. + // Once it is a governance param, update it using the keeper above. + prevInflationValue := tokenomicskeeper.MintPerClaimGlobalInflation + tokenomicskeeper.MintPerClaimGlobalInflation = 0 + t.Cleanup(func() { + tokenomicskeeper.MintPerClaimGlobalInflation = prevInflationValue + }) - // Add a new application - appStake := cosmostypes.NewCoin("upokt", math.NewInt(40000)) - expectedAppEndStakeZeroAmount := cosmostypes.NewCoin("upokt", math.NewInt(0)) - expectedAppBurn := appStake.AddAmount(math.NewInt(2000)) + // Add a new application with non-zero app stake end balance to assert against. + appStake := cosmostypes.NewCoin(volatile.DenomuPOKT, appInitialStake) app := apptypes.Application{ Address: sample.AccAddress(), Stake: &appStake, @@ -205,55 +225,34 @@ func TestProcessTokenLogicModules_AppStakeTooLow(t *testing.T) { } keepers.SetApplication(ctx, app) - // Query application balance prior to the accounting. - appStartBalance := getBalance(t, ctx, keepers, app.GetAddress()) - // Query application module balance prior to the accounting. - appModuleStartBalance := getBalance(t, ctx, keepers, appModuleAddress) + // Prepare the supplier revenue shares + supplierRevShares := make([]*sharedtypes.ServiceRevenueShare, len(supplierRevShareRatios)) + for i := range supplierRevShares { + shareHolderAddress := sample.AccAddress() + supplierRevShares[i] = &sharedtypes.ServiceRevenueShare{ + Address: shareHolderAddress, + RevSharePercentage: supplierRevShareRatios[i], + } + } // Add a new supplier. - supplierOwnerAddress := sample.AccAddress() - supplierStake := cosmostypes.NewCoin("upokt", math.NewInt(1000000)) + supplierStake := cosmostypes.NewCoin(volatile.DenomuPOKT, supplierInitialStake) supplier := sharedtypes.Supplier{ - OwnerAddress: supplierOwnerAddress, - OperatorAddress: supplierOwnerAddress, + // Make the first shareholder the supplier itself. + OwnerAddress: supplierRevShares[0].Address, + OperatorAddress: supplierRevShares[0].Address, Stake: &supplierStake, - Services: []*sharedtypes.SupplierServiceConfig{ - { - Service: service, - RevShare: []*sharedtypes.ServiceRevenueShare{ - { - Address: supplierOwnerAddress, - RevSharePercentage: 100, - }, - }, - }, - }, + Services: []*sharedtypes.SupplierServiceConfig{{Service: service, RevShare: supplierRevShares}}, } keepers.SetSupplier(ctx, supplier) - // Query supplier owner balance prior to the accounting. - supplierOwnerStartBalance := getBalance(t, ctx, keepers, supplier.GetOwnerAddress()) - - // Query supplier module balance prior to the accounting. + // Query the account and module start balances + appStartBalance := getBalance(t, ctx, keepers, app.GetAddress()) + appModuleStartBalance := getBalance(t, ctx, keepers, appModuleAddress) supplierModuleStartBalance := getBalance(t, ctx, keepers, supplierModuleAddress) - // Determine the number of relays to use up the application's entire stake - sharedParams := keepers.Keeper.GetParams(ctx) - numComputeUnits := expectedAppBurn.Amount.Uint64() / sharedParams.ComputeUnitsToTokensMultiplier - numRelays := numComputeUnits / service.ComputeUnitsPerRelay - - // The base claim whose root will be customized for testing purposes - claim := prooftypes.Claim{ - SupplierOperatorAddress: supplier.OperatorAddress, - SessionHeader: &sessiontypes.SessionHeader{ - ApplicationAddress: app.Address, - Service: service, - SessionId: "session_id", - SessionStartBlockHeight: 1, - SessionEndBlockHeight: testsession.GetSessionEndHeightWithDefaultParams(1), - }, - RootHash: testproof.SmstRootWithSumAndCount(numComputeUnits, numRelays), - } + // Prepare the claim for which the supplier did work for the application + claim := prepareClaim(numRelays, service, &app, &supplier) // Process the token logic modules err = keepers.ProcessTokenLogicModules(ctx, &claim) @@ -263,41 +262,54 @@ func TestProcessTokenLogicModules_AppStakeTooLow(t *testing.T) { appEndBalance := getBalance(t, ctx, keepers, app.GetAddress()) require.EqualValues(t, appStartBalance, appEndBalance) - // Assert that `applicationAddress` staked balance has gone to zero + // Determine the expected app end stake amount and the expected app burn + expectedAppBurn := math.NewInt(maxClaimableAmountPerSupplier) + expectedAppEndStakeAmount := appInitialStake.Sub(expectedAppBurn) + + // Assert that `applicationAddress` staked balance has decreased by the max claimable amount app, appIsFound := keepers.GetApplication(ctx, app.GetAddress()) + actualAppEndStakeAmount := app.GetStake().Amount require.True(t, appIsFound) - require.Equal(t, &expectedAppEndStakeZeroAmount, app.GetStake()) + require.Equal(t, expectedAppEndStakeAmount, actualAppEndStakeAmount) - // Assert that `apptypes.ModuleName` account module balance is *decreased* by the appropriate amount + // Sanity + require.Less(t, maxClaimableAmountPerSupplier, numTokensClaimed) + + // Assert that app module balance is *decreased* by the appropriate amount + // NB: The application module account burns the amount of uPOKT that was held in escrow + // on behalf of the applications which were serviced in a given session. + expectedAppModuleEndBalance := appModuleStartBalance.Sub(sdk.NewCoin(volatile.DenomuPOKT, expectedAppBurn)) appModuleEndBalance := getBalance(t, ctx, keepers, appModuleAddress) - expectedAppModuleEndBalance := appModuleStartBalance.Sub(appStake) require.NotNil(t, appModuleEndBalance) require.EqualValues(t, &expectedAppModuleEndBalance, appModuleEndBalance) - // Assert that `supplierOwnerAddress` account balance has *increased* by the appropriate amount - supplierOwnerEndBalance := getBalance(t, ctx, keepers, supplier.GetOwnerAddress()) - require.NotNil(t, supplierOwnerEndBalance) - - expectedSupplierBalance := supplierOwnerStartBalance.Add(expectedAppBurn) - require.EqualValues(t, &expectedSupplierBalance, supplierOwnerEndBalance) - // Assert that `supplierOperatorAddress` staked balance is *unchanged* supplier, supplierIsFound := keepers.GetSupplier(ctx, supplier.GetOperatorAddress()) require.True(t, supplierIsFound) require.Equal(t, &supplierStake, supplier.GetStake()) // Assert that `suppliertypes.ModuleName` account module balance is *unchanged* + // NB: Supplier rewards are minted to the supplier module account but then immediately + // distributed to the supplier accounts which provided service in a given session. supplierModuleEndBalance := getBalance(t, ctx, keepers, supplierModuleAddress) require.EqualValues(t, supplierModuleStartBalance, supplierModuleEndBalance) + // Assert that the supplier shareholders account balances have *increased* by + // the appropriate amount w.r.t token distribution. + shareAmounts := tokenomicskeeper.GetShareAmountMap(supplierRevShares, expectedAppBurn.Uint64()) + for shareHolderAddr, expectedShareAmount := range shareAmounts { + shareHolderBalance := getBalance(t, ctx, keepers, shareHolderAddr) + require.Equal(t, int64(expectedShareAmount), shareHolderBalance.Amount.Int64()) + } + // Check that the expected burn >> effective burn because application is overserviced - // events := sdkCtx.EventManager().Events() - // relayMiningEvents := testutilevents.FilterEvents[*tokenomicstypes.EventRelayMiningDifficultyUpdated](t, - // events, "poktroll.tokenomics.EventRelayMiningDifficultyUpdated") - // require.Len(t, relayMiningEvents, 1, "unexpected number of relay mining difficulty updated events") - // relayMiningEvent := relayMiningEvents[0] - // require.Equal(t, "svc1", relayMiningEvent.ServiceId) + sdkCtx := sdk.UnwrapSDKContext(ctx) + events := sdkCtx.EventManager().Events() + appOverservicedEvents := testutilevents.FilterEvents[*tokenomicstypes.EventApplicationOverserviced](t, + events, "poktroll.tokenomics.EventApplicationOverserviced") + require.Len(t, appOverservicedEvents, 1, "unexpected number of event overserviced events") + appOverservicedEvent := appOverservicedEvents[0] events := cosmostypes.UnwrapSDKContext(ctx).EventManager().Events() appAddrAttribute, _ := events.GetAttributes("application_addr") @@ -313,7 +325,7 @@ func TestProcessTokenLogicModules_AppStakeTooLow(t *testing.T) { err = json.Unmarshal([]byte(effectiveBurnAttribute[0].Value), &effectiveBurnEventCoin) require.NoError(t, err) - require.EqualValues(t, expectedAppBurn, expectedBurnEventCoin) + // require.EqualValues(t, expectedAppBurn, expectedBurnEventCoin) require.Greater(t, expectedBurnEventCoin.Amount.Uint64(), effectiveBurnEventCoin.Amount.Uint64()) } From 8663fac6cf2573347699e956edb9c168e6c17b73 Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Sun, 25 Aug 2024 13:00:54 -0400 Subject: [PATCH 10/31] Finished implementing TestProcessTokenLogicModules_TLMBurnEqualsMint_Invalid_SupplierExceedsMaxClaimableAmount --- api/poktroll/tokenomics/event.pulsar.go | 127 +++++++++--------- proto/poktroll/tokenomics/event.proto | 8 +- x/tokenomics/keeper/token_logic_modules.go | 28 +++- .../keeper/token_logic_modules_test.go | 105 +++++++-------- x/tokenomics/types/event.pb.go | 123 ++++++++--------- 5 files changed, 196 insertions(+), 195 deletions(-) diff --git a/api/poktroll/tokenomics/event.pulsar.go b/api/poktroll/tokenomics/event.pulsar.go index 25caeaa82..944d6be99 100644 --- a/api/poktroll/tokenomics/event.pulsar.go +++ b/api/poktroll/tokenomics/event.pulsar.go @@ -1818,18 +1818,18 @@ func (x *fastReflection_EventRelayMiningDifficultyUpdated) ProtoMethods() *proto } var ( - md_EventApplicationOverserviced protoreflect.MessageDescriptor - fd_EventApplicationOverserviced_application_addr protoreflect.FieldDescriptor - fd_EventApplicationOverserviced_supplier_addr protoreflect.FieldDescriptor - fd_EventApplicationOverserviced_expected_burn protoreflect.FieldDescriptor - fd_EventApplicationOverserviced_effective_burn protoreflect.FieldDescriptor + md_EventApplicationOverserviced protoreflect.MessageDescriptor + fd_EventApplicationOverserviced_application_addr protoreflect.FieldDescriptor + fd_EventApplicationOverserviced_supplier_operator_addr protoreflect.FieldDescriptor + fd_EventApplicationOverserviced_expected_burn protoreflect.FieldDescriptor + fd_EventApplicationOverserviced_effective_burn protoreflect.FieldDescriptor ) func init() { file_poktroll_tokenomics_event_proto_init() md_EventApplicationOverserviced = File_poktroll_tokenomics_event_proto.Messages().ByName("EventApplicationOverserviced") fd_EventApplicationOverserviced_application_addr = md_EventApplicationOverserviced.Fields().ByName("application_addr") - fd_EventApplicationOverserviced_supplier_addr = md_EventApplicationOverserviced.Fields().ByName("supplier_addr") + fd_EventApplicationOverserviced_supplier_operator_addr = md_EventApplicationOverserviced.Fields().ByName("supplier_operator_addr") fd_EventApplicationOverserviced_expected_burn = md_EventApplicationOverserviced.Fields().ByName("expected_burn") fd_EventApplicationOverserviced_effective_burn = md_EventApplicationOverserviced.Fields().ByName("effective_burn") } @@ -1905,9 +1905,9 @@ func (x *fastReflection_EventApplicationOverserviced) Range(f func(protoreflect. return } } - if x.SupplierAddr != "" { - value := protoreflect.ValueOfString(x.SupplierAddr) - if !f(fd_EventApplicationOverserviced_supplier_addr, value) { + if x.SupplierOperatorAddr != "" { + value := protoreflect.ValueOfString(x.SupplierOperatorAddr) + if !f(fd_EventApplicationOverserviced_supplier_operator_addr, value) { return } } @@ -1940,8 +1940,8 @@ func (x *fastReflection_EventApplicationOverserviced) Has(fd protoreflect.FieldD switch fd.FullName() { case "poktroll.tokenomics.EventApplicationOverserviced.application_addr": return x.ApplicationAddr != "" - case "poktroll.tokenomics.EventApplicationOverserviced.supplier_addr": - return x.SupplierAddr != "" + case "poktroll.tokenomics.EventApplicationOverserviced.supplier_operator_addr": + return x.SupplierOperatorAddr != "" case "poktroll.tokenomics.EventApplicationOverserviced.expected_burn": return x.ExpectedBurn != nil case "poktroll.tokenomics.EventApplicationOverserviced.effective_burn": @@ -1964,8 +1964,8 @@ func (x *fastReflection_EventApplicationOverserviced) Clear(fd protoreflect.Fiel switch fd.FullName() { case "poktroll.tokenomics.EventApplicationOverserviced.application_addr": x.ApplicationAddr = "" - case "poktroll.tokenomics.EventApplicationOverserviced.supplier_addr": - x.SupplierAddr = "" + case "poktroll.tokenomics.EventApplicationOverserviced.supplier_operator_addr": + x.SupplierOperatorAddr = "" case "poktroll.tokenomics.EventApplicationOverserviced.expected_burn": x.ExpectedBurn = nil case "poktroll.tokenomics.EventApplicationOverserviced.effective_burn": @@ -1989,8 +1989,8 @@ func (x *fastReflection_EventApplicationOverserviced) Get(descriptor protoreflec case "poktroll.tokenomics.EventApplicationOverserviced.application_addr": value := x.ApplicationAddr return protoreflect.ValueOfString(value) - case "poktroll.tokenomics.EventApplicationOverserviced.supplier_addr": - value := x.SupplierAddr + case "poktroll.tokenomics.EventApplicationOverserviced.supplier_operator_addr": + value := x.SupplierOperatorAddr return protoreflect.ValueOfString(value) case "poktroll.tokenomics.EventApplicationOverserviced.expected_burn": value := x.ExpectedBurn @@ -2020,8 +2020,8 @@ func (x *fastReflection_EventApplicationOverserviced) Set(fd protoreflect.FieldD switch fd.FullName() { case "poktroll.tokenomics.EventApplicationOverserviced.application_addr": x.ApplicationAddr = value.Interface().(string) - case "poktroll.tokenomics.EventApplicationOverserviced.supplier_addr": - x.SupplierAddr = value.Interface().(string) + case "poktroll.tokenomics.EventApplicationOverserviced.supplier_operator_addr": + x.SupplierOperatorAddr = value.Interface().(string) case "poktroll.tokenomics.EventApplicationOverserviced.expected_burn": x.ExpectedBurn = value.Message().Interface().(*v1beta1.Coin) case "poktroll.tokenomics.EventApplicationOverserviced.effective_burn": @@ -2058,8 +2058,8 @@ func (x *fastReflection_EventApplicationOverserviced) Mutable(fd protoreflect.Fi return protoreflect.ValueOfMessage(x.EffectiveBurn.ProtoReflect()) case "poktroll.tokenomics.EventApplicationOverserviced.application_addr": panic(fmt.Errorf("field application_addr of message poktroll.tokenomics.EventApplicationOverserviced is not mutable")) - case "poktroll.tokenomics.EventApplicationOverserviced.supplier_addr": - panic(fmt.Errorf("field supplier_addr of message poktroll.tokenomics.EventApplicationOverserviced is not mutable")) + case "poktroll.tokenomics.EventApplicationOverserviced.supplier_operator_addr": + panic(fmt.Errorf("field supplier_operator_addr of message poktroll.tokenomics.EventApplicationOverserviced is not mutable")) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.tokenomics.EventApplicationOverserviced")) @@ -2075,7 +2075,7 @@ func (x *fastReflection_EventApplicationOverserviced) NewField(fd protoreflect.F switch fd.FullName() { case "poktroll.tokenomics.EventApplicationOverserviced.application_addr": return protoreflect.ValueOfString("") - case "poktroll.tokenomics.EventApplicationOverserviced.supplier_addr": + case "poktroll.tokenomics.EventApplicationOverserviced.supplier_operator_addr": return protoreflect.ValueOfString("") case "poktroll.tokenomics.EventApplicationOverserviced.expected_burn": m := new(v1beta1.Coin) @@ -2156,7 +2156,7 @@ func (x *fastReflection_EventApplicationOverserviced) ProtoMethods() *protoiface if l > 0 { n += 1 + l + runtime.Sov(uint64(l)) } - l = len(x.SupplierAddr) + l = len(x.SupplierOperatorAddr) if l > 0 { n += 1 + l + runtime.Sov(uint64(l)) } @@ -2225,10 +2225,10 @@ func (x *fastReflection_EventApplicationOverserviced) ProtoMethods() *protoiface i-- dAtA[i] = 0x1a } - if len(x.SupplierAddr) > 0 { - i -= len(x.SupplierAddr) - copy(dAtA[i:], x.SupplierAddr) - i = runtime.EncodeVarint(dAtA, i, uint64(len(x.SupplierAddr))) + if len(x.SupplierOperatorAddr) > 0 { + i -= len(x.SupplierOperatorAddr) + copy(dAtA[i:], x.SupplierOperatorAddr) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.SupplierOperatorAddr))) i-- dAtA[i] = 0x12 } @@ -2322,7 +2322,7 @@ func (x *fastReflection_EventApplicationOverserviced) ProtoMethods() *protoiface iNdEx = postIndex case 2: if wireType != 2 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field SupplierAddr", wireType) + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field SupplierOperatorAddr", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -2350,7 +2350,7 @@ func (x *fastReflection_EventApplicationOverserviced) ProtoMethods() *protoiface if postIndex > l { return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF } - x.SupplierAddr = string(dAtA[iNdEx:postIndex]) + x.SupplierOperatorAddr = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 3: if wireType != 2 { @@ -2721,16 +2721,16 @@ type EventApplicationOverserviced struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - ApplicationAddr string `protobuf:"bytes,1,opt,name=application_addr,json=applicationAddr,proto3" json:"application_addr,omitempty"` - SupplierAddr string `protobuf:"bytes,2,opt,name=supplier_addr,json=supplierAddr,proto3" json:"supplier_addr,omitempty"` + ApplicationAddr string `protobuf:"bytes,1,opt,name=application_addr,json=applicationAddr,proto3" json:"application_addr,omitempty"` + SupplierOperatorAddr string `protobuf:"bytes,2,opt,name=supplier_operator_addr,json=supplierOperatorAddr,proto3" json:"supplier_operator_addr,omitempty"` // Expected burn is the amount the supplier is claiming for work done // to service the application during the session. - // This is usually the amount in the Claim object. + // This is usually the amount in the Claim submitted. ExpectedBurn *v1beta1.Coin `protobuf:"bytes,3,opt,name=expected_burn,json=expectedBurn,proto3" json:"expected_burn,omitempty"` // Effective burn is the amount that is actually being paid to the supplier // for the work done. It is less than the expected burn (claim amount) and - // most likely equal to the application's stake divided by the number of suppliers - // in a session. + // is a function of the relay mining algorithm. + // E.g. Te application's stake divided by the number of suppliers in a session. EffectiveBurn *v1beta1.Coin `protobuf:"bytes,4,opt,name=effective_burn,json=effectiveBurn,proto3" json:"effective_burn,omitempty"` } @@ -2761,9 +2761,9 @@ func (x *EventApplicationOverserviced) GetApplicationAddr() string { return "" } -func (x *EventApplicationOverserviced) GetSupplierAddr() string { +func (x *EventApplicationOverserviced) GetSupplierOperatorAddr() string { if x != nil { - return x.SupplierAddr + return x.SupplierOperatorAddr } return "" } @@ -2849,40 +2849,41 @@ var file_poktroll_tokenomics_event_proto_rawDesc = []byte{ 0x61, 0x79, 0x73, 0x45, 0x6d, 0x61, 0x12, 0x2b, 0x0a, 0x12, 0x6e, 0x65, 0x77, 0x5f, 0x6e, 0x75, 0x6d, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x5f, 0x65, 0x6d, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6e, 0x65, 0x77, 0x4e, 0x75, 0x6d, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x73, - 0x45, 0x6d, 0x61, 0x22, 0xf0, 0x01, 0x0a, 0x1c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x41, 0x70, 0x70, + 0x45, 0x6d, 0x61, 0x22, 0x81, 0x02, 0x0a, 0x1c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x64, 0x12, 0x29, 0x0a, 0x10, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x12, - 0x23, 0x0a, 0x0d, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x72, - 0x41, 0x64, 0x64, 0x72, 0x12, 0x3e, 0x0a, 0x0d, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, - 0x5f, 0x62, 0x75, 0x72, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, - 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x0c, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, - 0x42, 0x75, 0x72, 0x6e, 0x12, 0x40, 0x0a, 0x0e, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, - 0x65, 0x5f, 0x62, 0x75, 0x72, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, + 0x34, 0x0a, 0x16, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x5f, 0x6f, 0x70, 0x65, 0x72, + 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x14, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, + 0x72, 0x41, 0x64, 0x64, 0x72, 0x12, 0x3e, 0x0a, 0x0d, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, + 0x64, 0x5f, 0x62, 0x75, 0x72, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x0d, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, - 0x76, 0x65, 0x42, 0x75, 0x72, 0x6e, 0x2a, 0x60, 0x0a, 0x15, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x45, - 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, - 0x21, 0x0a, 0x1d, 0x45, 0x58, 0x50, 0x49, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, - 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, - 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x4d, 0x49, 0x53, 0x53, - 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x49, - 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x02, 0x42, 0xb8, 0x01, 0x0a, 0x17, 0x63, 0x6f, 0x6d, - 0x2e, 0x70, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2e, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, - 0x6d, 0x69, 0x63, 0x73, 0x42, 0x0a, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x50, 0x01, 0x5a, 0x24, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, - 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2f, 0x74, 0x6f, - 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0xa2, 0x02, 0x03, 0x50, 0x54, 0x58, 0xaa, 0x02, - 0x13, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, - 0x6d, 0x69, 0x63, 0x73, 0xca, 0x02, 0x13, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x5c, - 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0xe2, 0x02, 0x1f, 0x50, 0x6f, 0x6b, - 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x5c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, - 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x14, 0x50, - 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x3a, 0x3a, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, - 0x69, 0x63, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x0c, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, + 0x64, 0x42, 0x75, 0x72, 0x6e, 0x12, 0x40, 0x0a, 0x0e, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, + 0x76, 0x65, 0x5f, 0x62, 0x75, 0x72, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, + 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, + 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x0d, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, + 0x69, 0x76, 0x65, 0x42, 0x75, 0x72, 0x6e, 0x2a, 0x60, 0x0a, 0x15, 0x43, 0x6c, 0x61, 0x69, 0x6d, + 0x45, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, + 0x12, 0x21, 0x0a, 0x1d, 0x45, 0x58, 0x50, 0x49, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, + 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, + 0x44, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x4d, 0x49, 0x53, + 0x53, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, + 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x02, 0x42, 0xb8, 0x01, 0x0a, 0x17, 0x63, 0x6f, + 0x6d, 0x2e, 0x70, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2e, 0x74, 0x6f, 0x6b, 0x65, 0x6e, + 0x6f, 0x6d, 0x69, 0x63, 0x73, 0x42, 0x0a, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x50, 0x01, 0x5a, 0x24, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, + 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2f, 0x74, + 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0xa2, 0x02, 0x03, 0x50, 0x54, 0x58, 0xaa, + 0x02, 0x13, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, + 0x6f, 0x6d, 0x69, 0x63, 0x73, 0xca, 0x02, 0x13, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, + 0x5c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0xe2, 0x02, 0x1f, 0x50, 0x6f, + 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x5c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, + 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x14, + 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x3a, 0x3a, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, + 0x6d, 0x69, 0x63, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/proto/poktroll/tokenomics/event.proto b/proto/poktroll/tokenomics/event.proto index 9b07d8ae1..a536a1ae6 100644 --- a/proto/poktroll/tokenomics/event.proto +++ b/proto/poktroll/tokenomics/event.proto @@ -47,14 +47,14 @@ message EventRelayMiningDifficultyUpdated { // what a supplier is claiming (i.e. burn is not high enough). message EventApplicationOverserviced { string application_addr = 1; - string supplier_addr = 2; + string supplier_operator_addr = 2; // Expected burn is the amount the supplier is claiming for work done // to service the application during the session. - // This is usually the amount in the Claim object. + // This is usually the amount in the Claim submitted. cosmos.base.v1beta1.Coin expected_burn = 3; // Effective burn is the amount that is actually being paid to the supplier // for the work done. It is less than the expected burn (claim amount) and - // most likely equal to the application's stake divided by the number of suppliers - // in a session. + // is a function of the relay mining algorithm. + // E.g. Te application's stake divided by the number of suppliers in a session. cosmos.base.v1beta1.Coin effective_burn = 4; } \ No newline at end of file diff --git a/x/tokenomics/keeper/token_logic_modules.go b/x/tokenomics/keeper/token_logic_modules.go index 33f24e618..2d0a4aabc 100644 --- a/x/tokenomics/keeper/token_logic_modules.go +++ b/x/tokenomics/keeper/token_logic_modules.go @@ -37,6 +37,15 @@ const ( MintAllocationSupplier = 0.7 MintAllocationSourceOwner = 0.15 MintAllocationApplication = 0.0 + + // The percent difference that is allowable between the number of minted + // tokens in the tokenomics module and what is distributed to pocket network + // participants. + // This internal constant SHOULD ONLY be used in TokenLogicModuleGlobalMint. + // Due to floating point arithmetic, the total amount of minted coins may be slightly + // larger than what is distributed to pocket network participants + // TODO_MAINNET: Figure out if we can avoid this tolerance and use fixed point arithmetic. + mintDistributionAllowableTolerance = 0.02 ) type TokenLogicModule int @@ -155,6 +164,9 @@ func (k Keeper) ProcessTokenLogicModules( if err != nil { return tokenomicstypes.ErrTokenomicsRootHashInvalid.Wrapf("%v", err) } + if numRelays == 0 { + return tokenomicstypes.ErrTokenomicsRootHashInvalid.Wrap("root hash has zero relays") + } /* TODO_POST_MAINNET: Because of how things have evolved, we are now using @@ -343,6 +355,8 @@ func (k Keeper) TokenLogicModuleGlobalMint( // Determine how much new uPOKT to mint based on global inflation newMintCoin, newMintAmtFloat := calculateGlobalPerClaimMintInflationFromSettlementAmount(settlementCoin) + fmt.Println("OLSH ", newMintCoin, MintPerClaimGlobalInflation, settlementCoin) + // Mint new uPOKT to the tokenomics module account if err := k.bankKeeper.MintCoins(ctx, tokenomictypes.ModuleName, sdk.NewCoins(newMintCoin)); err != nil { return tokenomicstypes.ErrTokenomicsModuleMintFailed.Wrapf( @@ -406,11 +420,11 @@ func (k Keeper) TokenLogicModuleGlobalMint( coinDifference := new(big.Int).Sub(totalMintDistributedCoin.Amount.BigInt(), newMintCoin.Amount.BigInt()) coinDifference = coinDifference.Abs(coinDifference) percentDifference := new(big.Float).Quo(new(big.Float).SetInt(coinDifference), new(big.Float).SetInt(newMintCoin.Amount.BigInt())) - if percentDifference.Cmp(big.NewFloat(0.01)) > 0 { + if percentDifference.Cmp(big.NewFloat(mintDistributionAllowableTolerance)) > 0 { return tokenomictypes.ErrTokenomicsAmountMismatchTooLarge.Wrapf( - "the total distributed coins (%v) do not equal the amount of new minted coins (%v). Likely floating point arithmetic.\n"+ + "the total distributed coins (%v) do not equal the amount of newly minted coins (%v) with a percent difference of (%f). Likely floating point arithmetic.\n"+ "appCoin: %v, supplierCoin: %v, daoCoin: %v, serviceCoin: %v, proposerCoin: %v", - totalMintDistributedCoin, newMintCoin, + totalMintDistributedCoin, newMintCoin, percentDifference, appCoin, supplierCoin, daoCoin, serviceCoin, proposerCoin) } else if coinDifference.Cmp(big.NewInt(0)) > 0 { logger.Warn(fmt.Sprintf("Floating point arithmetic led to a discrepancy of %v (%f) between the total distributed coins (%v) and the amount of new minted coins (%v).\n"+ @@ -497,10 +511,10 @@ func (k Keeper) ensureClaimAmountLimits( // Prepare and emit the event for the application being overserviced applicationOverservicedEvent := &tokenomicstypes.EventApplicationOverserviced{ - ApplicationAddr: application.Address, - SupplierAddr: supplier.OperatorAddress, - ExpectedBurn: &claimSettlementCoin, - EffectiveBurn: &maxClaimableCoin, + ApplicationAddr: application.Address, + SupplierOperatorAddr: supplier.OperatorAddress, + ExpectedBurn: &claimSettlementCoin, + EffectiveBurn: &maxClaimableCoin, } eventManager := cosmostypes.UnwrapSDKContext(ctx).EventManager() if err := eventManager.EmitTypedEvent(applicationOverservicedEvent); err != nil { diff --git a/x/tokenomics/keeper/token_logic_modules_test.go b/x/tokenomics/keeper/token_logic_modules_test.go index 4bae90d8e..6174ca72c 100644 --- a/x/tokenomics/keeper/token_logic_modules_test.go +++ b/x/tokenomics/keeper/token_logic_modules_test.go @@ -7,7 +7,6 @@ import ( "testing" "cosmossdk.io/math" - "github.com/cometbft/cometbft/libs/json" cosmostypes "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -37,36 +36,25 @@ func init() { cmd.InitSDKConfig() } -// TODO_IN_THIS_PR: Add these tests or update existing tests to account for it. -// func TestProcessTokenLogicModules_HandleMaxClaimGreaterActualClaim(t *testing.T) {...} -// TODO_UPNEXT(@olshansk, #732): Add the following tests -// func TestProcessTokenLogicModules_ValidateAppOverServicingEvent(t *testing.T) {...} -// func TestProcessTokenLogicModules_ValidateAppReimbursedRequestEvent(t *testing.T) {...} - -func TestProcessTokenLogicModules_TLMBurnEqualsMintValid(t *testing.T) { +func TestProcessTokenLogicModules_TLMBurnEqualsMint_Valid(t *testing.T) { // Test Parameters appInitialStake := math.NewInt(1000000) supplierInitialStake := math.NewInt(1000000) supplierRevShareRatios := []float32{12.5, 37.5, 50} globalComputeUnitsToTokensMultiplier := uint64(1) serviceComputeUnitsPerRelay := uint64(1) + service := prepareTestService(serviceComputeUnitsPerRelay) numRelays := uint64(1000) // By supplier for application in this session + // Prepare the keepers + keepers, ctx := testkeeper.NewTokenomicsModuleKeepers(t, nil, testkeeper.WithService(*service)) + keepers.SetService(ctx, *service) + // Ensure the claim is within relay mining bounds numTokensClaimed := int64(numRelays * serviceComputeUnitsPerRelay * globalComputeUnitsToTokensMultiplier) maxClaimableAmountPerSupplier := appInitialStake.Quo(math.NewInt(sessionkeeper.NumSupplierPerSession)) require.GreaterOrEqual(t, maxClaimableAmountPerSupplier.Int64(), numTokensClaimed) - // Create a service that can be registered in the application and used in the claims - service := &sharedtypes.Service{ - Id: "svc1", - Name: "svcName1", - ComputeUnitsPerRelay: serviceComputeUnitsPerRelay, - OwnerAddress: sample.AccAddress(), - } - keepers, ctx := testkeeper.NewTokenomicsModuleKeepers(t, nil, testkeeper.WithService(*service)) - keepers.SetService(ctx, *service) - // Retrieve the app and supplier module addresses appModuleAddress := authtypes.NewModuleAddress(apptypes.ModuleName).String() supplierModuleAddress := authtypes.NewModuleAddress(suppliertypes.ModuleName).String() @@ -120,7 +108,7 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMintValid(t *testing.T) { supplierModuleStartBalance := getBalance(t, ctx, keepers, supplierModuleAddress) // Prepare the claim for which the supplier did work for the application - claim := prepareClaim(numRelays, service, &app, &supplier) + claim := prepareTestClaim(numRelays, service, &app, &supplier) // Process the token logic modules err = keepers.ProcessTokenLogicModules(ctx, &claim) @@ -131,8 +119,8 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMintValid(t *testing.T) { require.EqualValues(t, appStartBalance, appEndBalance) // Determine the expected app end stake amount and the expected app burn - expectedAppBurn := math.NewInt(numTokensClaimed) - expectedAppEndStakeAmount := appInitialStake.Sub(expectedAppBurn) + appBurn := math.NewInt(numTokensClaimed) + expectedAppEndStakeAmount := appInitialStake.Sub(appBurn) // Assert that `applicationAddress` staked balance has decreased by the appropriate amount app, appIsFound := keepers.GetApplication(ctx, app.GetAddress()) @@ -143,7 +131,7 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMintValid(t *testing.T) { // Assert that app module balance is *decreased* by the appropriate amount // NB: The application module account burns the amount of uPOKT that was held in escrow // on behalf of the applications which were serviced in a given session. - expectedAppModuleEndBalance := appModuleStartBalance.Sub(sdk.NewCoin(volatile.DenomuPOKT, expectedAppBurn)) + expectedAppModuleEndBalance := appModuleStartBalance.Sub(sdk.NewCoin(volatile.DenomuPOKT, appBurn)) appModuleEndBalance := getBalance(t, ctx, keepers, appModuleAddress) require.NotNil(t, appModuleEndBalance) require.EqualValues(t, &expectedAppModuleEndBalance, appModuleEndBalance) @@ -161,7 +149,7 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMintValid(t *testing.T) { // Assert that the supplier shareholders account balances have *increased* by // the appropriate amount w.r.t token distribution. - shareAmounts := tokenomicskeeper.GetShareAmountMap(supplierRevShares, expectedAppBurn.Uint64()) + shareAmounts := tokenomicskeeper.GetShareAmountMap(supplierRevShares, appBurn.Uint64()) for shareHolderAddr, expectedShareAmount := range shareAmounts { shareHolderBalance := getBalance(t, ctx, keepers, shareHolderAddr) require.Equal(t, int64(expectedShareAmount), shareHolderBalance.Amount.Int64()) @@ -171,14 +159,19 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMintValid(t *testing.T) { // DEV_NOTE: Most of the setup here is a copy-paste of TLMBurnEqualsMintValid // except that the application stake is calculated to explicitly be too low to // handle all the relays completed. -func TestProcessTokenLogicModules_TLMBurnEqualsMintInvalid_SupplierExceedsMaxClaimableAmount(t *testing.T) { +func TestProcessTokenLogicModules_TLMBurnEqualsMint_Invalid_SupplierExceedsMaxClaimableAmount(t *testing.T) { // Test Parameters globalComputeUnitsToTokensMultiplier := uint64(1) serviceComputeUnitsPerRelay := uint64(1) + service := prepareTestService(serviceComputeUnitsPerRelay) numRelays := uint64(1000) // By a single supplier for application in this session supplierInitialStake := math.NewInt(1000000) supplierRevShareRatios := []float32{12.5, 37.5, 50} + // Prepare the keepers + keepers, ctx := testkeeper.NewTokenomicsModuleKeepers(t, nil, testkeeper.WithService(*service)) + keepers.SetService(ctx, *service) + // Set up the relays to exceed the max claimable amount // Determine the max a supplier can claim maxClaimableAmountPerSupplier := int64(numRelays * serviceComputeUnitsPerRelay * globalComputeUnitsToTokensMultiplier) @@ -189,16 +182,6 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMintInvalid_SupplierExceedsMaxCla numRelays *= 5 numTokensClaimed := int64(numRelays * serviceComputeUnitsPerRelay * globalComputeUnitsToTokensMultiplier) - // Create a service that can be registered in the application and used in the claims - service := &sharedtypes.Service{ - Id: "svc1", - Name: "svcName1", - ComputeUnitsPerRelay: serviceComputeUnitsPerRelay, - OwnerAddress: sample.AccAddress(), - } - keepers, ctx := testkeeper.NewTokenomicsModuleKeepers(t, nil, testkeeper.WithService(*service)) - keepers.SetService(ctx, *service) - // Retrieve the app and supplier module addresses appModuleAddress := authtypes.NewModuleAddress(apptypes.ModuleName).String() supplierModuleAddress := authtypes.NewModuleAddress(suppliertypes.ModuleName).String() @@ -252,7 +235,7 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMintInvalid_SupplierExceedsMaxCla supplierModuleStartBalance := getBalance(t, ctx, keepers, supplierModuleAddress) // Prepare the claim for which the supplier did work for the application - claim := prepareClaim(numRelays, service, &app, &supplier) + claim := prepareTestClaim(numRelays, service, &app, &supplier) // Process the token logic modules err = keepers.ProcessTokenLogicModules(ctx, &claim) @@ -263,8 +246,9 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMintInvalid_SupplierExceedsMaxCla require.EqualValues(t, appStartBalance, appEndBalance) // Determine the expected app end stake amount and the expected app burn - expectedAppBurn := math.NewInt(maxClaimableAmountPerSupplier) - expectedAppEndStakeAmount := appInitialStake.Sub(expectedAppBurn) + appBurn := math.NewInt(maxClaimableAmountPerSupplier) + appBurnCoin := sdk.NewCoin(volatile.DenomuPOKT, appBurn) + expectedAppEndStakeAmount := appInitialStake.Sub(appBurn) // Assert that `applicationAddress` staked balance has decreased by the max claimable amount app, appIsFound := keepers.GetApplication(ctx, app.GetAddress()) @@ -278,7 +262,7 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMintInvalid_SupplierExceedsMaxCla // Assert that app module balance is *decreased* by the appropriate amount // NB: The application module account burns the amount of uPOKT that was held in escrow // on behalf of the applications which were serviced in a given session. - expectedAppModuleEndBalance := appModuleStartBalance.Sub(sdk.NewCoin(volatile.DenomuPOKT, expectedAppBurn)) + expectedAppModuleEndBalance := appModuleStartBalance.Sub(appBurnCoin) appModuleEndBalance := getBalance(t, ctx, keepers, appModuleAddress) require.NotNil(t, appModuleEndBalance) require.EqualValues(t, &expectedAppModuleEndBalance, appModuleEndBalance) @@ -296,7 +280,7 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMintInvalid_SupplierExceedsMaxCla // Assert that the supplier shareholders account balances have *increased* by // the appropriate amount w.r.t token distribution. - shareAmounts := tokenomicskeeper.GetShareAmountMap(supplierRevShares, expectedAppBurn.Uint64()) + shareAmounts := tokenomicskeeper.GetShareAmountMap(supplierRevShares, appBurn.Uint64()) for shareHolderAddr, expectedShareAmount := range shareAmounts { shareHolderBalance := getBalance(t, ctx, keepers, shareHolderAddr) require.Equal(t, int64(expectedShareAmount), shareHolderBalance.Amount.Int64()) @@ -311,22 +295,14 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMintInvalid_SupplierExceedsMaxCla require.Len(t, appOverservicedEvents, 1, "unexpected number of event overserviced events") appOverservicedEvent := appOverservicedEvents[0] - events := cosmostypes.UnwrapSDKContext(ctx).EventManager().Events() - appAddrAttribute, _ := events.GetAttributes("application_addr") - expectedBurnAttribute, _ := events.GetAttributes("expected_burn") - effectiveBurnAttribute, _ := events.GetAttributes("effective_burn") - - require.Equal(t, 1, len(appAddrAttribute)) - require.Equal(t, fmt.Sprintf("\"%s\"", app.GetAddress()), appAddrAttribute[0].Value) - - var expectedBurnEventCoin, effectiveBurnEventCoin cosmostypes.Coin - err = json.Unmarshal([]byte(expectedBurnAttribute[0].Value), &expectedBurnEventCoin) - require.NoError(t, err) - err = json.Unmarshal([]byte(effectiveBurnAttribute[0].Value), &effectiveBurnEventCoin) - require.NoError(t, err) + require.Equal(t, app.GetAddress(), appOverservicedEvent.ApplicationAddr) + require.Equal(t, supplier.GetOperatorAddress(), appOverservicedEvent.SupplierOperatorAddr) + require.Equal(t, numTokensClaimed, appOverservicedEvent.ExpectedBurn.Amount.Int64()) + require.Equal(t, appBurn, appOverservicedEvent.EffectiveBurn.Amount) + require.Less(t, appBurn.Int64(), numTokensClaimed) +} - // require.EqualValues(t, expectedAppBurn, expectedBurnEventCoin) - require.Greater(t, expectedBurnEventCoin.Amount.Uint64(), effectiveBurnEventCoin.Amount.Uint64()) +func TestProcessTokenLogicModules_TLMGlobalMint_Valid_CorrectMintDistribution(t *testing.T) { } func TestProcessTokenLogicModules_AppNotFound(t *testing.T) { @@ -361,10 +337,8 @@ func TestProcessTokenLogicModules_ServiceNotFound(t *testing.T) { claim := prooftypes.Claim{ SupplierOperatorAddress: supplierOperatorAddr, SessionHeader: &sessiontypes.SessionHeader{ - ApplicationAddress: appAddr, - Service: &sharedtypes.Service{ - Id: "non_existent_svc", - }, + ApplicationAddress: appAddr, + Service: &sharedtypes.Service{Id: "non_existent_svc"}, SessionId: "session_id", SessionStartBlockHeight: 1, SessionEndBlockHeight: testsession.GetSessionEndHeightWithDefaultParams(1), @@ -410,7 +384,7 @@ func TestProcessTokenLogicModules_InvalidRoot(t *testing.T) { root := make([]byte, protocol.TrieRootSize) // All 0s return root[:] }(), - errExpected: false, + errExpected: true, }, { desc: "correct size but invalid value", @@ -541,7 +515,9 @@ func TestProcessTokenLogicModules_InvalidClaim(t *testing.T) { } } -func prepareClaim( +// prepareTestClaim uses the given number of relays and compute unit per relay in the +// service provided to set up the test claim correctly. +func prepareTestClaim( numRelays uint64, service *sharedtypes.Service, app *apptypes.Application, @@ -559,7 +535,16 @@ func prepareClaim( }, RootHash: testproof.SmstRootWithSumAndCount(numComputeUnits, numRelays), } +} +// prepareTestService creates a service with the given compute units per relay. +func prepareTestService(serviceComputeUnitsPerRelay uint64) *sharedtypes.Service { + return &sharedtypes.Service{ + Id: "svc1", + Name: "svcName1", + ComputeUnitsPerRelay: serviceComputeUnitsPerRelay, + OwnerAddress: sample.AccAddress(), + } } func getBalance( diff --git a/x/tokenomics/types/event.pb.go b/x/tokenomics/types/event.pb.go index 648c6afbb..24d3052c8 100644 --- a/x/tokenomics/types/event.pb.go +++ b/x/tokenomics/types/event.pb.go @@ -276,16 +276,16 @@ func (m *EventRelayMiningDifficultyUpdated) GetNewNumRelaysEma() uint64 { // EventApplicationOverserviced is emitted when an application has less stake than // what a supplier is claiming (i.e. burn is not high enough). type EventApplicationOverserviced struct { - ApplicationAddr string `protobuf:"bytes,1,opt,name=application_addr,json=applicationAddr,proto3" json:"application_addr,omitempty"` - SupplierAddr string `protobuf:"bytes,2,opt,name=supplier_addr,json=supplierAddr,proto3" json:"supplier_addr,omitempty"` + ApplicationAddr string `protobuf:"bytes,1,opt,name=application_addr,json=applicationAddr,proto3" json:"application_addr,omitempty"` + SupplierOperatorAddr string `protobuf:"bytes,2,opt,name=supplier_operator_addr,json=supplierOperatorAddr,proto3" json:"supplier_operator_addr,omitempty"` // Expected burn is the amount the supplier is claiming for work done // to service the application during the session. - // This is usually the amount in the Claim object. + // This is usually the amount in the Claim submitted. ExpectedBurn *types1.Coin `protobuf:"bytes,3,opt,name=expected_burn,json=expectedBurn,proto3" json:"expected_burn,omitempty"` // Effective burn is the amount that is actually being paid to the supplier // for the work done. It is less than the expected burn (claim amount) and - // most likely equal to the application's stake divided by the number of suppliers - // in a session. + // is a function of the relay mining algorithm. + // E.g. Te application's stake divided by the number of suppliers in a session. EffectiveBurn *types1.Coin `protobuf:"bytes,4,opt,name=effective_burn,json=effectiveBurn,proto3" json:"effective_burn,omitempty"` } @@ -329,9 +329,9 @@ func (m *EventApplicationOverserviced) GetApplicationAddr() string { return "" } -func (m *EventApplicationOverserviced) GetSupplierAddr() string { +func (m *EventApplicationOverserviced) GetSupplierOperatorAddr() string { if m != nil { - return m.SupplierAddr + return m.SupplierOperatorAddr } return "" } @@ -361,53 +361,54 @@ func init() { func init() { proto.RegisterFile("poktroll/tokenomics/event.proto", fileDescriptor_a78874bbf91a58c7) } var fileDescriptor_a78874bbf91a58c7 = []byte{ - // 730 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x54, 0x4d, 0x4f, 0xdb, 0x48, - 0x18, 0x8e, 0x43, 0x58, 0x29, 0x03, 0x81, 0xc4, 0x2c, 0xda, 0x2c, 0x0b, 0x09, 0x64, 0xa5, 0x15, - 0xcb, 0x0a, 0x5b, 0x80, 0xb4, 0xa7, 0x15, 0xda, 0x24, 0x98, 0xc5, 0xd2, 0x92, 0x44, 0x0e, 0x54, - 0x55, 0x2f, 0x53, 0xc7, 0x7e, 0x93, 0x4c, 0x89, 0x67, 0xdc, 0xf1, 0x38, 0x09, 0xff, 0xa2, 0x3f, - 0xa0, 0x7f, 0xa0, 0x87, 0xfe, 0x8f, 0x1e, 0x39, 0xf6, 0x84, 0x2a, 0xb8, 0x71, 0xea, 0x4f, 0xa8, - 0x3c, 0xce, 0x57, 0x03, 0x55, 0xcf, 0xbd, 0x24, 0x93, 0xe7, 0x7d, 0x9e, 0xf7, 0xe3, 0x99, 0xc9, - 0x8b, 0x8a, 0x3e, 0xbb, 0x12, 0x9c, 0xf5, 0x7a, 0xba, 0x60, 0x57, 0x40, 0x99, 0x47, 0x9c, 0x40, - 0x87, 0x3e, 0x50, 0xa1, 0xf9, 0x9c, 0x09, 0xa6, 0xae, 0x8d, 0x09, 0xda, 0x94, 0xb0, 0x51, 0x70, - 0x58, 0xe0, 0xb1, 0x40, 0x6f, 0xd9, 0x01, 0xe8, 0xfd, 0x83, 0x16, 0x08, 0xfb, 0x40, 0x77, 0x18, - 0xa1, 0xb1, 0x68, 0xe3, 0xe7, 0x0e, 0xeb, 0x30, 0x79, 0xd4, 0xa3, 0xd3, 0x08, 0xdd, 0x98, 0xd4, - 0xf2, 0x39, 0x63, 0x6d, 0x5d, 0x5c, 0xfb, 0x10, 0xc4, 0xb1, 0xd2, 0xfb, 0x24, 0xca, 0x19, 0x51, - 0xd9, 0x6a, 0xcf, 0x26, 0x9e, 0x31, 0xf4, 0x09, 0x07, 0x57, 0xfd, 0x1b, 0x2d, 0x3a, 0xd1, 0xef, - 0xbc, 0xb2, 0xad, 0xec, 0x2e, 0x1d, 0xae, 0x6b, 0x93, 0x66, 0x64, 0x06, 0x4d, 0x92, 0x2b, 0xe9, - 0x87, 0xdb, 0x62, 0xcc, 0xb3, 0xe2, 0x2f, 0x75, 0x1f, 0x21, 0x1a, 0x7a, 0x98, 0x43, 0xcf, 0xbe, - 0x0e, 0xf2, 0xc9, 0x6d, 0x65, 0x37, 0x55, 0x59, 0x79, 0xb8, 0x2d, 0xce, 0xa0, 0x56, 0x9a, 0x86, - 0x9e, 0x25, 0x8f, 0x6a, 0x19, 0xe5, 0xa2, 0x80, 0xc3, 0x3c, 0x3f, 0x14, 0x80, 0x43, 0x4a, 0x44, - 0x90, 0x5f, 0x90, 0xaa, 0xf5, 0x87, 0xdb, 0xe2, 0xe3, 0xa0, 0xb5, 0x4a, 0x43, 0xaf, 0x1a, 0x23, - 0x97, 0x11, 0xa0, 0x52, 0x94, 0x83, 0xa8, 0x69, 0x5b, 0x10, 0x46, 0x31, 0x07, 0x3b, 0x60, 0x34, - 0x9f, 0xda, 0x56, 0x76, 0x57, 0x0e, 0xf7, 0xb4, 0x27, 0x2c, 0xd4, 0xa6, 0x73, 0x4a, 0x89, 0x25, - 0x15, 0x71, 0xb9, 0x47, 0x89, 0xac, 0x2c, 0xcc, 0x11, 0x4b, 0xef, 0xbe, 0xf2, 0xab, 0x09, 0x42, - 0xf4, 0x7e, 0x28, 0xbf, 0x5e, 0xa1, 0x9c, 0x6c, 0x09, 0x73, 0x78, 0x1d, 0x12, 0x0e, 0x1e, 0x50, - 0x31, 0xf2, 0xeb, 0x8f, 0xf9, 0xae, 0x1b, 0xd1, 0xa7, 0x35, 0xe5, 0xcd, 0x7a, 0xf5, 0x28, 0x89, - 0x95, 0xf5, 0xe7, 0xe8, 0xa5, 0xb7, 0x49, 0xb4, 0x23, 0xbd, 0x92, 0xed, 0x9f, 0x13, 0x4a, 0x68, - 0xe7, 0x84, 0xb4, 0xdb, 0xc4, 0x09, 0x7b, 0xe2, 0xfa, 0xd2, 0x77, 0x6d, 0x01, 0xae, 0xba, 0x85, - 0x50, 0x00, 0xbc, 0x4f, 0x1c, 0xc0, 0xc4, 0x95, 0x06, 0xa6, 0xad, 0xf4, 0x08, 0x31, 0x5d, 0xf5, - 0x18, 0x6d, 0xfa, 0x1c, 0xfa, 0x58, 0xd8, 0xbc, 0x03, 0x02, 0x77, 0xed, 0xa0, 0x8b, 0xbb, 0x30, - 0xc4, 0x40, 0x1d, 0xe6, 0x82, 0x2b, 0x4d, 0x4b, 0x5b, 0xf9, 0x88, 0x73, 0x21, 0x29, 0x67, 0x76, - 0xd0, 0x3d, 0x83, 0xa1, 0x11, 0xc7, 0xd5, 0x7f, 0xd0, 0x6f, 0x14, 0x06, 0xdf, 0x94, 0x2f, 0x48, - 0xf9, 0x2f, 0x14, 0x06, 0x4f, 0xaa, 0xf7, 0xd1, 0x9a, 0xac, 0x3e, 0xbd, 0x0f, 0x0c, 0x9e, 0x2d, - 0x0d, 0x4b, 0x45, 0x13, 0x43, 0xbf, 0x36, 0xbe, 0x1d, 0xc3, 0xb3, 0xd5, 0xbf, 0x90, 0x1a, 0x15, - 0x9b, 0x63, 0x2f, 0x4a, 0xf6, 0x2a, 0x85, 0xc1, 0x2c, 0xb9, 0xf4, 0x59, 0x41, 0x9b, 0xd2, 0x9e, - 0xb2, 0xef, 0xf7, 0x88, 0x23, 0x5f, 0x59, 0xbd, 0x0f, 0x7c, 0x34, 0xbb, 0xab, 0xfe, 0x89, 0xb2, - 0xf6, 0x34, 0x84, 0x6d, 0xd7, 0xe5, 0x23, 0x7f, 0x56, 0x67, 0xf0, 0xb2, 0xeb, 0x72, 0xf5, 0x77, - 0x94, 0x09, 0xc2, 0x08, 0x03, 0x1e, 0xf3, 0x62, 0x5b, 0x96, 0xc7, 0xa0, 0x24, 0x1d, 0xa3, 0x0c, - 0x0c, 0x7d, 0x70, 0x04, 0xb8, 0xb8, 0x15, 0x72, 0x2a, 0x87, 0x5f, 0x3a, 0xfc, 0x55, 0x8b, 0xb7, - 0x8a, 0x16, 0x6d, 0x15, 0x6d, 0xb4, 0x55, 0xb4, 0x2a, 0x23, 0xd4, 0x5a, 0x1e, 0xf3, 0x2b, 0x21, - 0xa7, 0xea, 0xbf, 0x68, 0x05, 0xda, 0x6d, 0x70, 0x04, 0xe9, 0x43, 0x9c, 0x20, 0xf5, 0xbd, 0x04, - 0x99, 0x89, 0x20, 0xca, 0xb0, 0xf7, 0x12, 0xad, 0x3f, 0xf9, 0xff, 0x53, 0x77, 0xd0, 0x96, 0xf1, - 0xbc, 0x61, 0x5a, 0xe5, 0x0b, 0xb3, 0x5e, 0xc3, 0x96, 0x51, 0x6e, 0xd6, 0x6b, 0xf8, 0xb2, 0xd6, - 0x6c, 0x18, 0x55, 0xf3, 0xd4, 0x34, 0x4e, 0xb2, 0x09, 0x35, 0x87, 0x32, 0x0d, 0xab, 0x5e, 0x3f, - 0xc5, 0xe7, 0x66, 0xb3, 0x69, 0xd6, 0xfe, 0xcb, 0x2a, 0x53, 0xc8, 0xac, 0x3d, 0x2b, 0xff, 0x6f, - 0x9e, 0x64, 0x93, 0x95, 0xf3, 0x0f, 0x77, 0x05, 0xe5, 0xe6, 0xae, 0xa0, 0x7c, 0xba, 0x2b, 0x28, - 0x6f, 0xee, 0x0b, 0x89, 0x9b, 0xfb, 0x42, 0xe2, 0xe3, 0x7d, 0x21, 0xf1, 0xe2, 0xa8, 0x43, 0x44, - 0x37, 0x6c, 0x69, 0x0e, 0xf3, 0xf4, 0xe8, 0xa1, 0xef, 0x53, 0x10, 0x03, 0xc6, 0xaf, 0xf4, 0xc9, - 0x76, 0x1c, 0xce, 0xee, 0x62, 0xb9, 0x24, 0x5b, 0x3f, 0xc9, 0x2d, 0x79, 0xf4, 0x25, 0x00, 0x00, - 0xff, 0xff, 0x0c, 0xdb, 0x5a, 0x92, 0xaf, 0x05, 0x00, 0x00, + // 740 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x54, 0x4f, 0x4f, 0xdb, 0x48, + 0x14, 0x8f, 0x43, 0x58, 0x29, 0xc3, 0x02, 0x89, 0x81, 0xdd, 0x2c, 0x0b, 0x09, 0xe4, 0xb0, 0x62, + 0x59, 0x61, 0x0b, 0x58, 0xed, 0x69, 0x85, 0x9a, 0x04, 0x53, 0x2c, 0x95, 0x24, 0x72, 0xa0, 0xaa, + 0x7a, 0x99, 0x3a, 0xf6, 0x4b, 0x32, 0x25, 0x9e, 0x71, 0xc7, 0xe3, 0x24, 0x1c, 0xfb, 0x0d, 0xfa, + 0x01, 0xfa, 0x05, 0x7a, 0xe8, 0xf7, 0xe8, 0x91, 0x63, 0x4f, 0xa8, 0x82, 0x1b, 0x9f, 0xa2, 0xf2, + 0x38, 0xff, 0x1a, 0xa8, 0x7a, 0xee, 0xc5, 0x1e, 0xff, 0xde, 0xef, 0xf7, 0xde, 0x9b, 0xdf, 0x8c, + 0x1f, 0x2a, 0xf8, 0xec, 0x52, 0x70, 0xd6, 0xed, 0xea, 0x82, 0x5d, 0x02, 0x65, 0x1e, 0x71, 0x02, + 0x1d, 0x7a, 0x40, 0x85, 0xe6, 0x73, 0x26, 0x98, 0xba, 0x32, 0x22, 0x68, 0x13, 0xc2, 0x7a, 0xde, + 0x61, 0x81, 0xc7, 0x02, 0xbd, 0x69, 0x07, 0xa0, 0xf7, 0xf6, 0x9b, 0x20, 0xec, 0x7d, 0xdd, 0x61, + 0x84, 0xc6, 0xa2, 0xf5, 0xd5, 0x36, 0x6b, 0x33, 0xb9, 0xd4, 0xa3, 0xd5, 0x10, 0x5d, 0x1f, 0xd7, + 0xf2, 0x39, 0x63, 0x2d, 0x5d, 0x5c, 0xf9, 0x10, 0xc4, 0xb1, 0xe2, 0xc7, 0x24, 0xca, 0x1a, 0x51, + 0xd9, 0x4a, 0xd7, 0x26, 0x9e, 0x31, 0xf0, 0x09, 0x07, 0x57, 0xfd, 0x0f, 0xcd, 0x3b, 0xd1, 0x77, + 0x4e, 0xd9, 0x52, 0x76, 0x16, 0x0e, 0xd6, 0xb4, 0x71, 0x33, 0x32, 0x83, 0x26, 0xc9, 0xe5, 0xf4, + 0xfd, 0x4d, 0x21, 0xe6, 0x59, 0xf1, 0x4b, 0xdd, 0x43, 0x88, 0x86, 0x1e, 0xe6, 0xd0, 0xb5, 0xaf, + 0x82, 0x5c, 0x72, 0x4b, 0xd9, 0x49, 0x95, 0x97, 0xee, 0x6f, 0x0a, 0x53, 0xa8, 0x95, 0xa6, 0xa1, + 0x67, 0xc9, 0xa5, 0x5a, 0x42, 0xd9, 0x28, 0xe0, 0x30, 0xcf, 0x0f, 0x05, 0xe0, 0x90, 0x12, 0x11, + 0xe4, 0xe6, 0xa4, 0x6a, 0xed, 0xfe, 0xa6, 0xf0, 0x30, 0x68, 0x2d, 0xd3, 0xd0, 0xab, 0xc4, 0xc8, + 0x45, 0x04, 0xa8, 0x14, 0x65, 0x21, 0x6a, 0xda, 0x16, 0x84, 0x51, 0xcc, 0xc1, 0x0e, 0x18, 0xcd, + 0xa5, 0xb6, 0x94, 0x9d, 0xa5, 0x83, 0x5d, 0xed, 0x11, 0x0b, 0xb5, 0xc9, 0x3e, 0xa5, 0xc4, 0x92, + 0x8a, 0xb8, 0xdc, 0x83, 0x44, 0x56, 0x06, 0x66, 0x88, 0xc5, 0x0f, 0xdf, 0xf8, 0xd5, 0x00, 0x21, + 0xba, 0x3f, 0x95, 0x5f, 0xaf, 0x51, 0x56, 0xb6, 0x84, 0x39, 0xbc, 0x09, 0x09, 0x07, 0x0f, 0xa8, + 0x18, 0xfa, 0xf5, 0xd7, 0x6c, 0xd7, 0xf5, 0xe8, 0x69, 0x4d, 0x78, 0xd3, 0x5e, 0x3d, 0x48, 0x62, + 0x65, 0xfc, 0x19, 0x7a, 0xf1, 0x7d, 0x12, 0x6d, 0x4b, 0xaf, 0x64, 0xfb, 0x67, 0x84, 0x12, 0xda, + 0x3e, 0x26, 0xad, 0x16, 0x71, 0xc2, 0xae, 0xb8, 0xba, 0xf0, 0x5d, 0x5b, 0x80, 0xab, 0x6e, 0x22, + 0x14, 0x00, 0xef, 0x11, 0x07, 0x30, 0x71, 0xa5, 0x81, 0x69, 0x2b, 0x3d, 0x44, 0x4c, 0x57, 0x3d, + 0x42, 0x1b, 0x3e, 0x87, 0x1e, 0x16, 0x36, 0x6f, 0x83, 0xc0, 0x1d, 0x3b, 0xe8, 0xe0, 0x0e, 0x0c, + 0x30, 0x50, 0x87, 0xb9, 0xe0, 0x4a, 0xd3, 0xd2, 0x56, 0x2e, 0xe2, 0x9c, 0x4b, 0xca, 0xa9, 0x1d, + 0x74, 0x4e, 0x61, 0x60, 0xc4, 0x71, 0xf5, 0x7f, 0xf4, 0x27, 0x85, 0xfe, 0x77, 0xe5, 0x73, 0x52, + 0xfe, 0x3b, 0x85, 0xfe, 0xa3, 0xea, 0x3d, 0xb4, 0x22, 0xab, 0x4f, 0xce, 0x03, 0x83, 0x67, 0x4b, + 0xc3, 0x52, 0xd1, 0x8e, 0xa1, 0x57, 0x1d, 0x9d, 0x8e, 0xe1, 0xd9, 0xea, 0x3f, 0x48, 0x8d, 0x8a, + 0xcd, 0xb0, 0xe7, 0x25, 0x7b, 0x99, 0x42, 0x7f, 0x9a, 0x5c, 0x7c, 0x9b, 0x44, 0x1b, 0xd2, 0x9e, + 0x92, 0xef, 0x77, 0x89, 0x23, 0x6f, 0x59, 0xad, 0x07, 0x7c, 0xb8, 0x77, 0x57, 0xfd, 0x1b, 0x65, + 0xec, 0x49, 0x08, 0xdb, 0xae, 0xcb, 0x87, 0xfe, 0x2c, 0x4f, 0xe1, 0x25, 0xd7, 0xe5, 0xea, 0xbf, + 0xe8, 0xb7, 0x20, 0x8c, 0x30, 0xe0, 0x98, 0xf9, 0xc0, 0x6d, 0xc1, 0x78, 0x2c, 0x88, 0xfd, 0x59, + 0x1d, 0x45, 0x6b, 0xc3, 0xa0, 0x54, 0x1d, 0xa1, 0x45, 0x18, 0xf8, 0xe0, 0x08, 0x70, 0x71, 0x33, + 0xe4, 0x54, 0xba, 0xb1, 0x70, 0xf0, 0x87, 0x16, 0x8f, 0x19, 0x2d, 0x1a, 0x33, 0xda, 0x70, 0xcc, + 0x68, 0x15, 0x46, 0xa8, 0xf5, 0xeb, 0x88, 0x5f, 0x0e, 0x39, 0x55, 0x9f, 0xa0, 0x25, 0x68, 0xb5, + 0xc0, 0x11, 0xa4, 0x07, 0x71, 0x82, 0xd4, 0x8f, 0x12, 0x2c, 0x8e, 0x05, 0x51, 0x86, 0xdd, 0x57, + 0x68, 0xed, 0xd1, 0x1f, 0x52, 0xdd, 0x46, 0x9b, 0xc6, 0x8b, 0xba, 0x69, 0x95, 0xce, 0xcd, 0x5a, + 0x15, 0x5b, 0x46, 0xa9, 0x51, 0xab, 0xe2, 0x8b, 0x6a, 0xa3, 0x6e, 0x54, 0xcc, 0x13, 0xd3, 0x38, + 0xce, 0x24, 0xd4, 0x2c, 0x5a, 0xac, 0x5b, 0xb5, 0xda, 0x09, 0x3e, 0x33, 0x1b, 0x0d, 0xb3, 0xfa, + 0x34, 0xa3, 0x4c, 0x20, 0xb3, 0xfa, 0xbc, 0xf4, 0xcc, 0x3c, 0xce, 0x24, 0xcb, 0x67, 0x9f, 0x6e, + 0xf3, 0xca, 0xf5, 0x6d, 0x5e, 0xf9, 0x72, 0x9b, 0x57, 0xde, 0xdd, 0xe5, 0x13, 0xd7, 0x77, 0xf9, + 0xc4, 0xe7, 0xbb, 0x7c, 0xe2, 0xe5, 0x61, 0x9b, 0x88, 0x4e, 0xd8, 0xd4, 0x1c, 0xe6, 0xe9, 0xd1, + 0xcd, 0xdf, 0xa3, 0x20, 0xfa, 0x8c, 0x5f, 0xea, 0xe3, 0x71, 0x39, 0x98, 0x1e, 0xce, 0x72, 0x6a, + 0x36, 0x7f, 0x91, 0x63, 0xf3, 0xf0, 0x6b, 0x00, 0x00, 0x00, 0xff, 0xff, 0xb1, 0x9c, 0x4b, 0x68, + 0xc0, 0x05, 0x00, 0x00, } func (m *EventClaimExpired) Marshal() (dAtA []byte, err error) { @@ -608,10 +609,10 @@ func (m *EventApplicationOverserviced) MarshalToSizedBuffer(dAtA []byte) (int, e i-- dAtA[i] = 0x1a } - if len(m.SupplierAddr) > 0 { - i -= len(m.SupplierAddr) - copy(dAtA[i:], m.SupplierAddr) - i = encodeVarintEvent(dAtA, i, uint64(len(m.SupplierAddr))) + if len(m.SupplierOperatorAddr) > 0 { + i -= len(m.SupplierOperatorAddr) + copy(dAtA[i:], m.SupplierOperatorAddr) + i = encodeVarintEvent(dAtA, i, uint64(len(m.SupplierOperatorAddr))) i-- dAtA[i] = 0x12 } @@ -717,7 +718,7 @@ func (m *EventApplicationOverserviced) Size() (n int) { if l > 0 { n += 1 + l + sovEvent(uint64(l)) } - l = len(m.SupplierAddr) + l = len(m.SupplierOperatorAddr) if l > 0 { n += 1 + l + sovEvent(uint64(l)) } @@ -1271,7 +1272,7 @@ func (m *EventApplicationOverserviced) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field SupplierAddr", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field SupplierOperatorAddr", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -1299,7 +1300,7 @@ func (m *EventApplicationOverserviced) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.SupplierAddr = string(dAtA[iNdEx:postIndex]) + m.SupplierOperatorAddr = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 3: if wireType != 2 { From 085d13487fd22de9288817a7456d78b87bcc548d Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Sun, 25 Aug 2024 15:09:51 -0400 Subject: [PATCH 11/31] Implemented TestProcessTokenLogicModules_TLMGlobalMint_Valid_MintDistributionCorrect --- testutil/keeper/tokenomics.go | 13 ++ testutil/sample/sample.go | 23 ++-- .../keeper_settle_pending_claims_test.go | 2 +- x/tokenomics/keeper/token_logic_modules.go | 31 +++-- .../keeper/token_logic_modules_test.go | 129 +++++++++++++++++- x/tokenomics/types/errors.go | 1 + 6 files changed, 167 insertions(+), 32 deletions(-) diff --git a/testutil/keeper/tokenomics.go b/testutil/keeper/tokenomics.go index 6ec0e64df..008b29be2 100644 --- a/testutil/keeper/tokenomics.go +++ b/testutil/keeper/tokenomics.go @@ -460,3 +460,16 @@ func WithService(service sharedtypes.Service) TokenomicsModuleKeepersOpt { return ctx } } + +func WithProposerAddr(addr string) TokenomicsModuleKeepersOpt { + return func(ctx context.Context, keepers *TokenomicsModuleKeepers) context.Context { + valAddr, err := cosmostypes.ValAddressFromBech32(addr) + if err != nil { + panic(err) + } + consensusAddr := cosmostypes.ConsAddress(valAddr) + sdkCtx := sdk.UnwrapSDKContext(ctx) + sdkCtx = sdkCtx.WithProposer(consensusAddr) + return sdkCtx + } +} diff --git a/testutil/sample/sample.go b/testutil/sample/sample.go index 7bf7a7d3c..c9b91d874 100644 --- a/testutil/sample/sample.go +++ b/testutil/sample/sample.go @@ -1,6 +1,8 @@ package sample import ( + "encoding/hex" + "github.com/cometbft/cometbft/crypto/tmhash" "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" @@ -17,25 +19,28 @@ func AccAddressAndPubKey() (string, cryptotypes.PubKey) { // AccAddress returns a sample account address func AccAddress() string { - // TODO_BETA(@olshansk): Change this to secp256k1 because that's what we'll - // use in production for all real accounts. + addr, _ := AccAddressAndPubKey() + return addr +} + +// AccAddressAndPubKeyEdd2519 returns a sample account address and public key +func AccAddressAndPubKeyEdd2519() (string, cryptotypes.PubKey) { pk := ed25519.GenPrivKey().PubKey() addr := pk.Address() - return sdk.AccAddress(addr).String() + return sdk.AccAddress(addr).String(), pk } // ConsAddress returns a sample consensus address, which has the prefix // of validators (i.e. consensus nodes) when converted to bech32. func ConsAddress() string { - pk := ed25519.GenPrivKey().PubKey() + _, pk := AccAddressAndPubKey() consensusAddress := tmhash.SumTruncated(pk.Address()) valAddress := sdk.ValAddress(consensusAddress) return valAddress.String() } -// AccAddressAndPubKeyEdd2519 returns a sample account address and public key -func AccAddressAndPubKeyEdd2519() (string, cryptotypes.PubKey) { - pk := ed25519.GenPrivKey().PubKey() - addr := pk.Address() - return sdk.AccAddress(addr).String(), pk +func AccAddressFromConsAddress(validatorConsAddr string) string { + valAddr, _ := sdk.ValAddressFromBech32(validatorConsAddr) + proposerAddress, _ := sdk.AccAddressFromHexUnsafe(hex.EncodeToString(valAddr.Bytes())) + return proposerAddress.String() } diff --git a/x/tokenomics/keeper/keeper_settle_pending_claims_test.go b/x/tokenomics/keeper/keeper_settle_pending_claims_test.go index cdb9d8e98..94f873791 100644 --- a/x/tokenomics/keeper/keeper_settle_pending_claims_test.go +++ b/x/tokenomics/keeper/keeper_settle_pending_claims_test.go @@ -141,7 +141,7 @@ func (s *TestSuite) SetupTest() { require.NoError(t, err) // Construct a valid session tree with 10 relays. - s.numRelays = uint64(10) + s.numRelays = uint64(100) sessionTree := testtree.NewFilledSessionTree( sdkCtx, t, s.numRelays, service.ComputeUnitsPerRelay, diff --git a/x/tokenomics/keeper/token_logic_modules.go b/x/tokenomics/keeper/token_logic_modules.go index 2d0a4aabc..c41b046fc 100644 --- a/x/tokenomics/keeper/token_logic_modules.go +++ b/x/tokenomics/keeper/token_logic_modules.go @@ -27,7 +27,7 @@ import ( var ( // Governance parameters for the TLMGlobalMint module // TODO_UPNEXT(@olshansk, #732): Make this a governance parameter and give it a non-zero value + tests. - MintPerClaimGlobalInflation = 0.1 + MintPerClaimedTokenGlobalInflation = 0.1 ) const ( @@ -45,7 +45,7 @@ const ( // Due to floating point arithmetic, the total amount of minted coins may be slightly // larger than what is distributed to pocket network participants // TODO_MAINNET: Figure out if we can avoid this tolerance and use fixed point arithmetic. - mintDistributionAllowableTolerance = 0.02 + MintDistributionAllowableTolerance = 0.02 ) type TokenLogicModule int @@ -347,15 +347,16 @@ func (k Keeper) TokenLogicModuleGlobalMint( ) error { logger := k.Logger().With("method", "TokenLogicModuleGlobalMint") - if MintPerClaimGlobalInflation == 0 { + if MintPerClaimedTokenGlobalInflation == 0 { logger.Warn("global inflation is set to zero. Skipping Global Mint TLM.") return nil } // Determine how much new uPOKT to mint based on global inflation newMintCoin, newMintAmtFloat := calculateGlobalPerClaimMintInflationFromSettlementAmount(settlementCoin) - - fmt.Println("OLSH ", newMintCoin, MintPerClaimGlobalInflation, settlementCoin) + if newMintCoin.Amount.Int64() == 0 { + return tokenomicstypes.ErrTokenomicsMintAmountZero + } // Mint new uPOKT to the tokenomics module account if err := k.bankKeeper.MintCoins(ctx, tokenomictypes.ModuleName, sdk.NewCoins(newMintCoin)); err != nil { @@ -365,14 +366,14 @@ func (k Keeper) TokenLogicModuleGlobalMint( logger.Info(fmt.Sprintf("minted (%v) coins in the tokenomics module", newMintCoin)) // Send a portion of the rewards to the application - appCoin, err := k.sendRewardsToAccount(ctx, tokenomictypes.ModuleName, application.Address, newMintAmtFloat, MintAllocationApplication) + appCoin, err := k.sendRewardsToAccount(ctx, tokenomictypes.ModuleName, application.Address, &newMintAmtFloat, MintAllocationApplication) if err != nil { return tokenomictypes.ErrTokenomicsSendingMintRewards.Wrapf("sending rewards to application: %v", err) } logger.Debug(fmt.Sprintf("sent (%v) newley minted coins from the tokenomics module to the application with address %q", appCoin, application.Address)) // Send a portion of the rewards to the supplier shareholders. - supplierCoinsToShareAmt := calculateAllocationAmount(newMintAmtFloat, MintAllocationSupplier) + supplierCoinsToShareAmt := calculateAllocationAmount(&newMintAmtFloat, MintAllocationSupplier) supplierCoin := cosmostypes.NewCoin(volatile.DenomuPOKT, math.NewInt(supplierCoinsToShareAmt)) // Send funds from the tokenomics module to the supplier module account if err = k.bankKeeper.SendCoinsFromModuleToModule(ctx, tokenomicstypes.ModuleName, suppliertypes.ModuleName, sdk.NewCoins(supplierCoin)); err != nil { @@ -394,14 +395,14 @@ func (k Keeper) TokenLogicModuleGlobalMint( logger.Debug(fmt.Sprintf("sent (%v) newley minted coins from the tokenomics module to the supplier with address %q", supplierCoin, supplier.OperatorAddress)) // Send a portion of the rewards to the DAO - daoCoin, err := k.sendRewardsToAccount(ctx, tokenomictypes.ModuleName, k.GetAuthority(), newMintAmtFloat, MintAllocationDAO) + daoCoin, err := k.sendRewardsToAccount(ctx, tokenomictypes.ModuleName, k.GetAuthority(), &newMintAmtFloat, MintAllocationDAO) if err != nil { return tokenomictypes.ErrTokenomicsSendingMintRewards.Wrapf("sending rewards to DAO: %v", err) } logger.Debug(fmt.Sprintf("sent (%v) newley minted coins from the tokenomics module to the DAO with address %q", daoCoin, k.GetAuthority())) // Send a portion of the rewards to the source owner - serviceCoin, err := k.sendRewardsToAccount(ctx, tokenomictypes.ModuleName, service.OwnerAddress, newMintAmtFloat, MintAllocationSourceOwner) + serviceCoin, err := k.sendRewardsToAccount(ctx, tokenomictypes.ModuleName, service.OwnerAddress, &newMintAmtFloat, MintAllocationSourceOwner) if err != nil { return tokenomictypes.ErrTokenomicsSendingMintRewards.Wrapf("sending rewards to source owner: %v", err) } @@ -409,7 +410,7 @@ func (k Keeper) TokenLogicModuleGlobalMint( // Send a portion of the rewards to the block proposer proposerAddr := cosmostypes.AccAddress(sdk.UnwrapSDKContext(ctx).BlockHeader().ProposerAddress).String() - proposerCoin, err := k.sendRewardsToAccount(ctx, tokenomictypes.ModuleName, proposerAddr, newMintAmtFloat, MintAllocationProposer) + proposerCoin, err := k.sendRewardsToAccount(ctx, tokenomictypes.ModuleName, proposerAddr, &newMintAmtFloat, MintAllocationProposer) if err != nil { return tokenomictypes.ErrTokenomicsSendingMintRewards.Wrapf("sending rewards to proposer: %v", err) } @@ -420,7 +421,7 @@ func (k Keeper) TokenLogicModuleGlobalMint( coinDifference := new(big.Int).Sub(totalMintDistributedCoin.Amount.BigInt(), newMintCoin.Amount.BigInt()) coinDifference = coinDifference.Abs(coinDifference) percentDifference := new(big.Float).Quo(new(big.Float).SetInt(coinDifference), new(big.Float).SetInt(newMintCoin.Amount.BigInt())) - if percentDifference.Cmp(big.NewFloat(mintDistributionAllowableTolerance)) > 0 { + if percentDifference.Cmp(big.NewFloat(MintDistributionAllowableTolerance)) > 0 { return tokenomictypes.ErrTokenomicsAmountMismatchTooLarge.Wrapf( "the total distributed coins (%v) do not equal the amount of newly minted coins (%v) with a percent difference of (%f). Likely floating point arithmetic.\n"+ "appCoin: %v, supplierCoin: %v, daoCoin: %v, serviceCoin: %v, proposerCoin: %v", @@ -498,7 +499,7 @@ func (k Keeper) ensureClaimAmountLimits( maxClaimableCoin := sdk.NewCoin(volatile.DenomuPOKT, appStake.Amount.Quo(math.NewInt(sessionkeeper.NumSupplierPerSession))) if maxClaimableCoin.Amount.GTE(claimSettlementCoin.Amount) { - logger.Info(fmt.Sprintf("Claim by supplier %s IS WITHIN LIMITS of servicing application %s. Max claimable amount < Claim amount: %v < %v", + logger.Info(fmt.Sprintf("Claim by supplier %s IS WITHIN LIMITS of servicing application %s. Max claimable amount >= Claim amount: %v >= %v", supplier.OperatorAddress, application.Address, maxClaimableCoin, claimSettlementCoin.Amount)) return claimSettlementCoin, nil } @@ -606,14 +607,14 @@ func (k Keeper) distributeSupplierRewardsToShareHolders( // calculateGlobalPerClaimMintInflationFromSettlementAmount calculates the amount // of uPOKT to mint based on the global per claim inflation rate as a function of // the settlement amount for a particular claim(s) or session(s). -func calculateGlobalPerClaimMintInflationFromSettlementAmount(settlementCoin sdk.Coin) (sdk.Coin, *big.Float) { +func calculateGlobalPerClaimMintInflationFromSettlementAmount(settlementCoin sdk.Coin) (sdk.Coin, big.Float) { // Determine how much new uPOKT to mint based on global per claim inflation. // TODO_MAINNET: Consider using fixed point arithmetic for deterministic results. settlementAmtFloat := new(big.Float).SetUint64(settlementCoin.Amount.Uint64()) - newMintAmtFloat := new(big.Float).Mul(settlementAmtFloat, big.NewFloat(MintPerClaimGlobalInflation)) + newMintAmtFloat := new(big.Float).Mul(settlementAmtFloat, big.NewFloat(MintPerClaimedTokenGlobalInflation)) newMintAmtInt, _ := newMintAmtFloat.Int64() mintAmtCoin := cosmostypes.NewCoin(volatile.DenomuPOKT, math.NewInt(newMintAmtInt)) - return mintAmtCoin, newMintAmtFloat + return mintAmtCoin, *newMintAmtFloat } // calculateAllocationAmount does big float arithmetic to determine the absolute diff --git a/x/tokenomics/keeper/token_logic_modules_test.go b/x/tokenomics/keeper/token_logic_modules_test.go index 6174ca72c..d8ac3ef5e 100644 --- a/x/tokenomics/keeper/token_logic_modules_test.go +++ b/x/tokenomics/keeper/token_logic_modules_test.go @@ -11,6 +11,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" "github.com/pokt-network/smt" "github.com/stretchr/testify/require" @@ -36,6 +37,9 @@ func init() { cmd.InitSDKConfig() } +// TODO_IMPROVE: Consider using a TestSuite, similar to `x/tokenomics/keeper/keeper_settle_pending_claims_test.go` +// for the TLM based tests in this file. + func TestProcessTokenLogicModules_TLMBurnEqualsMint_Valid(t *testing.T) { // Test Parameters appInitialStake := math.NewInt(1000000) @@ -66,10 +70,10 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMint_Valid(t *testing.T) { require.NoError(t, err) // TODO_TECHDEBT: Setting inflation to zero so we are testing the BurnEqualsMint logic exclusively. // Once it is a governance param, update it using the keeper above. - prevInflationValue := tokenomicskeeper.MintPerClaimGlobalInflation - tokenomicskeeper.MintPerClaimGlobalInflation = 0 + prevInflationValue := tokenomicskeeper.MintPerClaimedTokenGlobalInflation + tokenomicskeeper.MintPerClaimedTokenGlobalInflation = 0 t.Cleanup(func() { - tokenomicskeeper.MintPerClaimGlobalInflation = prevInflationValue + tokenomicskeeper.MintPerClaimedTokenGlobalInflation = prevInflationValue }) // Add a new application with non-zero app stake end balance to assert against. @@ -193,10 +197,10 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMint_Invalid_SupplierExceedsMaxCl require.NoError(t, err) // TODO_TECHDEBT: Setting inflation to zero so we are testing the BurnEqualsMint logic exclusively. // Once it is a governance param, update it using the keeper above. - prevInflationValue := tokenomicskeeper.MintPerClaimGlobalInflation - tokenomicskeeper.MintPerClaimGlobalInflation = 0 + prevInflationValue := tokenomicskeeper.MintPerClaimedTokenGlobalInflation + tokenomicskeeper.MintPerClaimedTokenGlobalInflation = 0 t.Cleanup(func() { - tokenomicskeeper.MintPerClaimGlobalInflation = prevInflationValue + tokenomicskeeper.MintPerClaimedTokenGlobalInflation = prevInflationValue }) // Add a new application with non-zero app stake end balance to assert against. @@ -302,7 +306,118 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMint_Invalid_SupplierExceedsMaxCl require.Less(t, appBurn.Int64(), numTokensClaimed) } -func TestProcessTokenLogicModules_TLMGlobalMint_Valid_CorrectMintDistribution(t *testing.T) { +func TestProcessTokenLogicModules_TLMGlobalMint_Valid_MintDistributionCorrect(t *testing.T) { + // Test Parameters + appInitialStake := math.NewInt(1000000) + supplierInitialStake := math.NewInt(1000000) + supplierRevShareRatios := []float32{12.5, 37.5, 50} + globalComputeUnitsToTokensMultiplier := uint64(1) + serviceComputeUnitsPerRelay := uint64(1) + service := prepareTestService(serviceComputeUnitsPerRelay) + numRelays := uint64(1000) // By supplier for application in this session + numTokensClaimed := float64(numRelays * serviceComputeUnitsPerRelay * globalComputeUnitsToTokensMultiplier) + validatorConsAddr := sample.ConsAddress() + + // Prepare the keepers + keepers, ctx := testkeeper.NewTokenomicsModuleKeepers(t, nil, testkeeper.WithService(*service), testkeeper.WithProposerAddr(validatorConsAddr)) + keepers.SetService(ctx, *service) + + // Set compute_units_to_tokens_multiplier to simplify expectation calculations. + err := keepers.Keeper.SetParams(ctx, tokenomicstypes.Params{ + ComputeUnitsToTokensMultiplier: globalComputeUnitsToTokensMultiplier, + }) + require.NoError(t, err) + + // Add a new application with non-zero app stake end balance to assert against. + appStake := cosmostypes.NewCoin(volatile.DenomuPOKT, appInitialStake) + app := apptypes.Application{ + Address: sample.AccAddress(), + Stake: &appStake, + ServiceConfigs: []*sharedtypes.ApplicationServiceConfig{{Service: service}}, + } + keepers.SetApplication(ctx, app) + + // Prepare the supplier revenue shares + supplierRevShares := make([]*sharedtypes.ServiceRevenueShare, len(supplierRevShareRatios)) + for i := range supplierRevShares { + shareHolderAddress := sample.AccAddress() + supplierRevShares[i] = &sharedtypes.ServiceRevenueShare{ + Address: shareHolderAddress, + RevSharePercentage: supplierRevShareRatios[i], + } + } + + // Add a new supplier. + supplierStake := cosmostypes.NewCoin(volatile.DenomuPOKT, supplierInitialStake) + supplier := sharedtypes.Supplier{ + // Make the first shareholder the supplier itself. + OwnerAddress: supplierRevShares[0].Address, + OperatorAddress: supplierRevShares[0].Address, + Stake: &supplierStake, + Services: []*sharedtypes.SupplierServiceConfig{{Service: service, RevShare: supplierRevShares}}, + } + keepers.SetSupplier(ctx, supplier) + + // Prepare the claim for which the supplier did work for the application + claim := prepareTestClaim(numRelays, service, &app, &supplier) + + // Prepare addresses + daoAddr := authtypes.NewModuleAddress(govtypes.ModuleName) + appAddress := app.Address + proposerAddress := sample.AccAddressFromConsAddress(validatorConsAddr) + // supplierOperatorAddr := supplier.OperatorAddress + + // Determine balances before inflation + daoBalanceBefore := getBalance(t, ctx, keepers, daoAddr.String()) + propBalanceBefore := getBalance(t, ctx, keepers, proposerAddress) + serviceOwnerBalanceBefore := getBalance(t, ctx, keepers, service.OwnerAddress) + appBalanceBefore := getBalance(t, ctx, keepers, appAddress) + supplierShareholderBalancesBefore := make(map[string]*sdk.Coin, len(supplierRevShares)) + for _, revShare := range supplierRevShares { + addr := revShare.Address + supplierShareholderBalancesBefore[addr] = getBalance(t, ctx, keepers, addr) + } + + // Process the token logic modules + err = keepers.ProcessTokenLogicModules(ctx, &claim) + require.NoError(t, err) + + // Determine balances after inflation + daoBalanceAfter := getBalance(t, ctx, keepers, daoAddr.String()) + propBalanceAfter := getBalance(t, ctx, keepers, proposerAddress) + serviceOwnerBalanceAfter := getBalance(t, ctx, keepers, service.OwnerAddress) + appBalanceAfter := getBalance(t, ctx, keepers, appAddress) + supplierShareholderBalancesAfter := make(map[string]*sdk.Coin, len(supplierRevShares)) + for _, revShare := range supplierRevShares { + addr := revShare.Address + supplierShareholderBalancesAfter[addr] = getBalance(t, ctx, keepers, addr) + } + + // Compute mint per actor + numTokensMinted := numTokensClaimed * tokenomicskeeper.MintPerClaimedTokenGlobalInflation + daoMint := math.NewInt(int64(numTokensMinted * tokenomicskeeper.MintAllocationDAO)) + propMint := math.NewInt(int64(numTokensMinted * tokenomicskeeper.MintAllocationProposer)) + serviceOwnerMint := math.NewInt(int64(numTokensMinted * tokenomicskeeper.MintAllocationSourceOwner)) + appMint := math.NewInt(int64(numTokensMinted * tokenomicskeeper.MintAllocationApplication)) + supplierMint := float32(numTokensMinted * tokenomicskeeper.MintAllocationSupplier) + + // Ensure the balance was increase be the appropriate amount + require.Equal(t, daoBalanceBefore.Amount.Add(daoMint), daoBalanceAfter.Amount) + require.Equal(t, propBalanceBefore.Amount.Add(propMint), propBalanceAfter.Amount) + require.Equal(t, serviceOwnerBalanceBefore.Amount.Add(serviceOwnerMint), serviceOwnerBalanceAfter.Amount) + require.Equal(t, appBalanceBefore.Amount.Add(appMint), appBalanceAfter.Amount) + for _, revShare := range supplierRevShares { + addr := revShare.Address + balanceBefore := supplierShareholderBalancesBefore[addr] + balanceAfter := supplierShareholderBalancesAfter[addr].Amount.Int64() + mintShare := int64(supplierMint * revShare.RevSharePercentage / 100) + rewardShare := int64(float32(numTokensClaimed) * revShare.RevSharePercentage / 100) + balanceIncrease := math.NewInt(mintShare + rewardShare) + expectedBalanceAfter := balanceBefore.Amount.Add(balanceIncrease).Int64() + // TODO_MAINNET: Remove the InDelta check and use the exact amount once the floating point arithmetic is fixed + acceptableRoundingDelta := tokenomicskeeper.MintDistributionAllowableTolerance * float64(balanceAfter) + require.InDelta(t, expectedBalanceAfter, balanceAfter, acceptableRoundingDelta) + } } func TestProcessTokenLogicModules_AppNotFound(t *testing.T) { diff --git a/x/tokenomics/types/errors.go b/x/tokenomics/types/errors.go index 018c44601..f5f1c7e1a 100644 --- a/x/tokenomics/types/errors.go +++ b/x/tokenomics/types/errors.go @@ -34,4 +34,5 @@ var ( ErrTokenomicsSupplierRevShareFailed = sdkerrors.Register(ModuleName, 1125, "failed to send rev share to supplier shareholders") ErrTokenomicsApplicationReimbursementRequestFailed = sdkerrors.Register(ModuleName, 1126, "failed to send application reimbursement request event") ErrTokenomicsAmountMismatchTooLarge = sdkerrors.Register(ModuleName, 1127, "an unexpected amount mismatch occurred") + ErrTokenomicsMintAmountZero = sdkerrors.Register(ModuleName, 1128, "mint amount cannot be zero") ) From 1de13ba277dc23c6a34faa29dec3f58f5c6cff7e Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Sun, 25 Aug 2024 15:16:30 -0400 Subject: [PATCH 12/31] Updated comments in e2e/tests/0_settlement.feature --- e2e/tests/0_settlement.feature | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/e2e/tests/0_settlement.feature b/e2e/tests/0_settlement.feature index 89ab2527c..ec7042940 100644 --- a/e2e/tests/0_settlement.feature +++ b/e2e/tests/0_settlement.feature @@ -7,7 +7,7 @@ Feature: Tokenomics Namespace - Scenario: Mint equals burn when a claim is created and a valid proof is submitted and required + Scenario: TLM Mint=Burn when a valid claim is within max limits Given the user has the pocketd binary installed # Network preparation and validation And an account exists for "supplier1" @@ -25,23 +25,12 @@ Feature: Tokenomics Namespace Then the account balance of "supplier1" should be "420" uPOKT "more" than before And the "application" stake of "app1" should be "420" uPOKT "less" than before - Scenario: - Given the user has the pocketd binary installed - # Network preparation - And an account exists for "supplier1" - And the "supplier" account for "supplier1" is staked - And an account exists for "app1" - And the "application" account for "app1" is staked - And the service "anvil" registered for application "app1" has a compute units per relay of "1" - # Start servicing relays - When the supplier "supplier1" has serviced a session with "10" relays for service "anvil" for application "app1" - # Wait for the Claim & Proof lifecycle - And the user should wait for the "tokenomics" module "ClaimSettled" end block event to be broadcast - - # TODO_IN_THIS_PR: Add the following test - # Scenario: Supplier overservices an application and gets paid for less work than claimed - # TODO_ADDTEST: Implement the following scenarios + # Scenario: Supplier revenue shares are properly distributedTestUpdateRelayMiningDifficulty_NewServiceSeenForTheFirstTime + # Scenario: TLM Mint=Burn when a valid claim is outside Max Limits + # - Ensure over serviced event is submitted + # Scenario: TLM GlobalMint properly distributes minted rewards to all actors + # - Ensure reimbursement request is submitted # Scenario: Mint equals burn when a claim is created and a valid proof is submitted but not required # Scenario: No emissions or burn when a claim is created and an invalid proof is submitted # Scenario: No emissions or burn when a claim is created and a proof is required but is not submitted From b8dff51a47556f6b65fc5cf081c50eb10b3e419e Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Sun, 25 Aug 2024 15:27:03 -0400 Subject: [PATCH 13/31] Fixed failing unit test --- e2e/tests/0_settlement.feature | 2 +- .../relay_mining_difficulty_test.go | 46 ++++++++++--------- testutil/integration/app.go | 7 +-- testutil/testrelayer/relays.go | 20 +++++++- 4 files changed, 48 insertions(+), 27 deletions(-) diff --git a/e2e/tests/0_settlement.feature b/e2e/tests/0_settlement.feature index ec7042940..2503b6a68 100644 --- a/e2e/tests/0_settlement.feature +++ b/e2e/tests/0_settlement.feature @@ -26,7 +26,7 @@ Feature: Tokenomics Namespace And the "application" stake of "app1" should be "420" uPOKT "less" than before # TODO_ADDTEST: Implement the following scenarios - # Scenario: Supplier revenue shares are properly distributedTestUpdateRelayMiningDifficulty_NewServiceSeenForTheFirstTime + # Scenario: Supplier revenue shares are properly distributed # Scenario: TLM Mint=Burn when a valid claim is outside Max Limits # - Ensure over serviced event is submitted # Scenario: TLM GlobalMint properly distributes minted rewards to all actors diff --git a/tests/integration/tokenomics/relay_mining_difficulty_test.go b/tests/integration/tokenomics/relay_mining_difficulty_test.go index 3b3a2d876..498486320 100644 --- a/tests/integration/tokenomics/relay_mining_difficulty_test.go +++ b/tests/integration/tokenomics/relay_mining_difficulty_test.go @@ -39,8 +39,9 @@ func TestUpdateRelayMiningDifficulty_NewServiceSeenForTheFirstTime(t *testing.T) session := getSession(t, integrationApp) sharedParams := getSharedParams(t, integrationApp) - // Prepare the trie with a single mined relay - trie := prepareSMST(t, sdkCtx, integrationApp, session) + // Prepare the trie with several mined relays + numRelays := uint64(100) + trie := prepareSMST(t, sdkCtx, integrationApp, session, numRelays) // Compute the number of blocks to wait between different events // TODO_BLOCKER(@bryanchriswhite): See this comment: https://github.com/pokt-network/poktroll/pull/610#discussion_r1645777322 @@ -118,8 +119,8 @@ func TestUpdateRelayMiningDifficulty_NewServiceSeenForTheFirstTime(t *testing.T) require.Equal(t, prooftypes.DefaultRelayDifficultyTargetHashHex, relayMiningEvent.NewTargetHashHexEncoded) // The previous EMA is the same as the current one if the service is new - require.Equal(t, uint64(1), relayMiningEvent.PrevNumRelaysEma) - require.Equal(t, uint64(1), relayMiningEvent.NewNumRelaysEma) + require.Equal(t, numRelays, relayMiningEvent.PrevNumRelaysEma) + require.Equal(t, numRelays, relayMiningEvent.NewNumRelaysEma) } func UpdateRelayMiningDifficulty_UpdatingMultipleServicesAtOnce(t *testing.T) {} @@ -164,11 +165,12 @@ func getSession(t *testing.T, integrationApp *testutil.App) *sessiontypes.Sessio return getSessionRes.Session } -// prepareSMST prepares an SMST with a single mined relay for the given session. +// prepareSMST prepares an SMST with a the number of mined relays specified. func prepareSMST( t *testing.T, ctx context.Context, integrationApp *testutil.App, session *sessiontypes.Session, + numRelays uint64, ) *smt.SMST { t.Helper() @@ -178,23 +180,25 @@ func prepareSMST( kvStore, err := pebble.NewKVStore("") require.NoError(t, err) - // NB: A signed mined relay is a MinedRelay type with the appropriate - // payload, signatures and metadata populated. - // - // It does not (as of writing) adhere to the actual on-chain difficulty (i.e. - // hash check) of the test service surrounding the scope of this test. - minedRelay := testrelayer.NewSignedMinedRelay(t, ctx, - session, - integrationApp.DefaultApplication.Address, - integrationApp.DefaultSupplier.OperatorAddress, - integrationApp.DefaultSupplierKeyringKeyringUid, - integrationApp.GetKeyRing(), - integrationApp.GetRingClient(), - ) - trie := smt.NewSparseMerkleSumTrie(kvStore, protocol.NewTrieHasher(), smt.WithValueHasher(nil)) - err = trie.Update(minedRelay.Hash, minedRelay.Bytes, 1) - require.NoError(t, err) + + for i := uint64(0); i < numRelays; i++ { + // DEV_NOTE: A signed mined relay is a MinedRelay type with the appropriate + // payload, signatures and metadata populated. + // It does not (as of writing) adhere to the actual on-chain difficulty (i.e. + // hash check) of the test service surrounding the scope of this test. + minedRelay := testrelayer.NewSignedMinedRelay(t, ctx, + session, + integrationApp.DefaultApplication.Address, + integrationApp.DefaultSupplier.OperatorAddress, + integrationApp.DefaultSupplierKeyringKeyringUid, + integrationApp.GetKeyRing(), + integrationApp.GetRingClient(), + ) + + err = trie.Update(minedRelay.Hash, minedRelay.Bytes, 1) + require.NoError(t, err) + } return trie } diff --git a/testutil/integration/app.go b/testutil/integration/app.go index ccd56beba..7f46755ca 100644 --- a/testutil/integration/app.go +++ b/testutil/integration/app.go @@ -509,9 +509,10 @@ func NewCompleteIntegrationApp(t *testing.T) *App { // Prepare a new default service defaultService := sharedtypes.Service{ - Id: "svc1", - Name: "svcName1", - OwnerAddress: sample.AccAddress(), + Id: "svc1", + Name: "svcName1", + ComputeUnitsPerRelay: 1, + OwnerAddress: sample.AccAddress(), } serviceKeeper.SetService(integrationApp.sdkCtx, defaultService) integrationApp.DefaultService = &defaultService diff --git a/testutil/testrelayer/relays.go b/testutil/testrelayer/relays.go index 14da2aace..83bc75ab4 100644 --- a/testutil/testrelayer/relays.go +++ b/testutil/testrelayer/relays.go @@ -5,11 +5,13 @@ import ( "fmt" "strings" "testing" + "time" "github.com/cosmos/cosmos-sdk/crypto/keyring" cosmostypes "github.com/cosmos/cosmos-sdk/types" signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" "github.com/stretchr/testify/require" + "golang.org/x/exp/rand" "github.com/pokt-network/poktroll/pkg/crypto" "github.com/pokt-network/poktroll/pkg/crypto/protocol" @@ -93,13 +95,13 @@ func NewSignedMinedRelay( SessionHeader: session.Header, SupplierOperatorAddress: supplierOperatorAddr, }, - Payload: []byte("request_payload"), + Payload: randomPayload(), }, Res: &servicetypes.RelayResponse{ Meta: servicetypes.RelayResponseMetadata{ SessionHeader: session.Header, }, - Payload: []byte("response_payload"), + Payload: randomPayload(), }, } @@ -234,3 +236,17 @@ func NewEmptyRelay(reqHeader, resHeader *sessiontypes.SessionHeader, supplierOpe }, } } + +const ( + charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + payloadLength = 32 +) + +func randomPayload() []byte { + rand.Seed(uint64(time.Now().UnixNano())) + bz := make([]byte, payloadLength) + for i := range bz { + bz[i] = charset[rand.Intn(len(charset))] + } + return bz +} From 4c335e7dd53aa8f766d63cd9b854aa2fb29f15e3 Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Mon, 26 Aug 2024 17:20:27 -0400 Subject: [PATCH 14/31] update compile proto --- x/tokenomics/types/tx.pb.go | 1 - 1 file changed, 1 deletion(-) diff --git a/x/tokenomics/types/tx.pb.go b/x/tokenomics/types/tx.pb.go index 91f06eeff..5bc7d33e4 100644 --- a/x/tokenomics/types/tx.pb.go +++ b/x/tokenomics/types/tx.pb.go @@ -133,7 +133,6 @@ type MsgUpdateParam struct { // specified in the `Params` message in `proof/params.proto.` Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` // Types that are valid to be assigned to AsType: - // // *MsgUpdateParam_AsString // *MsgUpdateParam_AsInt64 // *MsgUpdateParam_AsBytes From f7a0da7cfd613909db5985b9de393755cde7954d Mon Sep 17 00:00:00 2001 From: Redouane Lakrache Date: Thu, 19 Sep 2024 23:30:51 +0200 Subject: [PATCH 15/31] fix: Remove merge added lines --- config.yml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/config.yml b/config.yml index 0a9041d5d..7921b0573 100644 --- a/config.yml +++ b/config.yml @@ -188,20 +188,6 @@ genesis: # `supplier1_stake_config.yaml` so that the stake command causes a state change. amount: "1000068" denom: upokt - - address: pokt1ad28jdap2zfanjd7hpkh984yveney6k9a42man - delegatee_gateway_addresses: [] - service_configs: - - service: - id: anvil - - service: - id: rest - - service: - id: ollama - stake: - # NB: This value should be exactly 1upokt smaller than the value in - # `supplier1_stake_config.yaml` so that the stake command causes a state change. - amount: "1000068" - denom: upokt supplier: supplierList: - owner_address: pokt19a3t4yunp0dlpfjrp7qwnzwlrzd5fzs2gjaaaj From 79ac3e66f9901587d5f3ddcb879ceb70ab24d68e Mon Sep 17 00:00:00 2001 From: Redouane Lakrache Date: Fri, 20 Sep 2024 22:55:26 +0200 Subject: [PATCH 16/31] feat: Add GMRR --- api/poktroll/tokenomics/event.pulsar.go | 798 +++++++++++++++++++-- proto/poktroll/tokenomics/event.proto | 9 + x/tokenomics/keeper/token_logic_modules.go | 113 ++- x/tokenomics/types/errors.go | 3 +- x/tokenomics/types/event.pb.go | 437 +++++++++-- 5 files changed, 1258 insertions(+), 102 deletions(-) diff --git a/api/poktroll/tokenomics/event.pulsar.go b/api/poktroll/tokenomics/event.pulsar.go index 0090b4632..fbeaf5572 100644 --- a/api/poktroll/tokenomics/event.pulsar.go +++ b/api/poktroll/tokenomics/event.pulsar.go @@ -3006,6 +3006,633 @@ func (x *fastReflection_EventSupplierSlashed) ProtoMethods() *protoiface.Methods } } +var ( + md_EventApplicationReimbursementRequest protoreflect.MessageDescriptor + fd_EventApplicationReimbursementRequest_application_addr protoreflect.FieldDescriptor + fd_EventApplicationReimbursementRequest_service_id protoreflect.FieldDescriptor + fd_EventApplicationReimbursementRequest_session_id protoreflect.FieldDescriptor + fd_EventApplicationReimbursementRequest_amount protoreflect.FieldDescriptor +) + +func init() { + file_poktroll_tokenomics_event_proto_init() + md_EventApplicationReimbursementRequest = File_poktroll_tokenomics_event_proto.Messages().ByName("EventApplicationReimbursementRequest") + fd_EventApplicationReimbursementRequest_application_addr = md_EventApplicationReimbursementRequest.Fields().ByName("application_addr") + fd_EventApplicationReimbursementRequest_service_id = md_EventApplicationReimbursementRequest.Fields().ByName("service_id") + fd_EventApplicationReimbursementRequest_session_id = md_EventApplicationReimbursementRequest.Fields().ByName("session_id") + fd_EventApplicationReimbursementRequest_amount = md_EventApplicationReimbursementRequest.Fields().ByName("amount") +} + +var _ protoreflect.Message = (*fastReflection_EventApplicationReimbursementRequest)(nil) + +type fastReflection_EventApplicationReimbursementRequest EventApplicationReimbursementRequest + +func (x *EventApplicationReimbursementRequest) ProtoReflect() protoreflect.Message { + return (*fastReflection_EventApplicationReimbursementRequest)(x) +} + +func (x *EventApplicationReimbursementRequest) slowProtoReflect() protoreflect.Message { + mi := &file_poktroll_tokenomics_event_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_EventApplicationReimbursementRequest_messageType fastReflection_EventApplicationReimbursementRequest_messageType +var _ protoreflect.MessageType = fastReflection_EventApplicationReimbursementRequest_messageType{} + +type fastReflection_EventApplicationReimbursementRequest_messageType struct{} + +func (x fastReflection_EventApplicationReimbursementRequest_messageType) Zero() protoreflect.Message { + return (*fastReflection_EventApplicationReimbursementRequest)(nil) +} +func (x fastReflection_EventApplicationReimbursementRequest_messageType) New() protoreflect.Message { + return new(fastReflection_EventApplicationReimbursementRequest) +} +func (x fastReflection_EventApplicationReimbursementRequest_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_EventApplicationReimbursementRequest +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_EventApplicationReimbursementRequest) Descriptor() protoreflect.MessageDescriptor { + return md_EventApplicationReimbursementRequest +} + +// 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_EventApplicationReimbursementRequest) Type() protoreflect.MessageType { + return _fastReflection_EventApplicationReimbursementRequest_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_EventApplicationReimbursementRequest) New() protoreflect.Message { + return new(fastReflection_EventApplicationReimbursementRequest) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_EventApplicationReimbursementRequest) Interface() protoreflect.ProtoMessage { + return (*EventApplicationReimbursementRequest)(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_EventApplicationReimbursementRequest) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if x.ApplicationAddr != "" { + value := protoreflect.ValueOfString(x.ApplicationAddr) + if !f(fd_EventApplicationReimbursementRequest_application_addr, value) { + return + } + } + if x.ServiceId != "" { + value := protoreflect.ValueOfString(x.ServiceId) + if !f(fd_EventApplicationReimbursementRequest_service_id, value) { + return + } + } + if x.SessionId != "" { + value := protoreflect.ValueOfString(x.SessionId) + if !f(fd_EventApplicationReimbursementRequest_session_id, value) { + return + } + } + if x.Amount != nil { + value := protoreflect.ValueOfMessage(x.Amount.ProtoReflect()) + if !f(fd_EventApplicationReimbursementRequest_amount, 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_EventApplicationReimbursementRequest) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + case "poktroll.tokenomics.EventApplicationReimbursementRequest.application_addr": + return x.ApplicationAddr != "" + case "poktroll.tokenomics.EventApplicationReimbursementRequest.service_id": + return x.ServiceId != "" + case "poktroll.tokenomics.EventApplicationReimbursementRequest.session_id": + return x.SessionId != "" + case "poktroll.tokenomics.EventApplicationReimbursementRequest.amount": + return x.Amount != nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.tokenomics.EventApplicationReimbursementRequest")) + } + panic(fmt.Errorf("message poktroll.tokenomics.EventApplicationReimbursementRequest 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_EventApplicationReimbursementRequest) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + case "poktroll.tokenomics.EventApplicationReimbursementRequest.application_addr": + x.ApplicationAddr = "" + case "poktroll.tokenomics.EventApplicationReimbursementRequest.service_id": + x.ServiceId = "" + case "poktroll.tokenomics.EventApplicationReimbursementRequest.session_id": + x.SessionId = "" + case "poktroll.tokenomics.EventApplicationReimbursementRequest.amount": + x.Amount = nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.tokenomics.EventApplicationReimbursementRequest")) + } + panic(fmt.Errorf("message poktroll.tokenomics.EventApplicationReimbursementRequest 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_EventApplicationReimbursementRequest) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + case "poktroll.tokenomics.EventApplicationReimbursementRequest.application_addr": + value := x.ApplicationAddr + return protoreflect.ValueOfString(value) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.service_id": + value := x.ServiceId + return protoreflect.ValueOfString(value) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.session_id": + value := x.SessionId + return protoreflect.ValueOfString(value) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.amount": + value := x.Amount + return protoreflect.ValueOfMessage(value.ProtoReflect()) + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.tokenomics.EventApplicationReimbursementRequest")) + } + panic(fmt.Errorf("message poktroll.tokenomics.EventApplicationReimbursementRequest 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_EventApplicationReimbursementRequest) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + case "poktroll.tokenomics.EventApplicationReimbursementRequest.application_addr": + x.ApplicationAddr = value.Interface().(string) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.service_id": + x.ServiceId = value.Interface().(string) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.session_id": + x.SessionId = value.Interface().(string) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.amount": + x.Amount = value.Message().Interface().(*v1beta1.Coin) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.tokenomics.EventApplicationReimbursementRequest")) + } + panic(fmt.Errorf("message poktroll.tokenomics.EventApplicationReimbursementRequest 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_EventApplicationReimbursementRequest) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "poktroll.tokenomics.EventApplicationReimbursementRequest.amount": + if x.Amount == nil { + x.Amount = new(v1beta1.Coin) + } + return protoreflect.ValueOfMessage(x.Amount.ProtoReflect()) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.application_addr": + panic(fmt.Errorf("field application_addr of message poktroll.tokenomics.EventApplicationReimbursementRequest is not mutable")) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.service_id": + panic(fmt.Errorf("field service_id of message poktroll.tokenomics.EventApplicationReimbursementRequest is not mutable")) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.session_id": + panic(fmt.Errorf("field session_id of message poktroll.tokenomics.EventApplicationReimbursementRequest is not mutable")) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.tokenomics.EventApplicationReimbursementRequest")) + } + panic(fmt.Errorf("message poktroll.tokenomics.EventApplicationReimbursementRequest 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_EventApplicationReimbursementRequest) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "poktroll.tokenomics.EventApplicationReimbursementRequest.application_addr": + return protoreflect.ValueOfString("") + case "poktroll.tokenomics.EventApplicationReimbursementRequest.service_id": + return protoreflect.ValueOfString("") + case "poktroll.tokenomics.EventApplicationReimbursementRequest.session_id": + return protoreflect.ValueOfString("") + case "poktroll.tokenomics.EventApplicationReimbursementRequest.amount": + m := new(v1beta1.Coin) + return protoreflect.ValueOfMessage(m.ProtoReflect()) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.tokenomics.EventApplicationReimbursementRequest")) + } + panic(fmt.Errorf("message poktroll.tokenomics.EventApplicationReimbursementRequest 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_EventApplicationReimbursementRequest) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in poktroll.tokenomics.EventApplicationReimbursementRequest", 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_EventApplicationReimbursementRequest) 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_EventApplicationReimbursementRequest) 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_EventApplicationReimbursementRequest) 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_EventApplicationReimbursementRequest) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*EventApplicationReimbursementRequest) + 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.ApplicationAddr) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + l = len(x.ServiceId) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + l = len(x.SessionId) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + if x.Amount != nil { + l = options.Size(x.Amount) + 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().(*EventApplicationReimbursementRequest) + 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.Amount != nil { + encoded, err := options.Marshal(x.Amount) + 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] = 0x22 + } + if len(x.SessionId) > 0 { + i -= len(x.SessionId) + copy(dAtA[i:], x.SessionId) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.SessionId))) + i-- + dAtA[i] = 0x1a + } + if len(x.ServiceId) > 0 { + i -= len(x.ServiceId) + copy(dAtA[i:], x.ServiceId) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.ServiceId))) + i-- + dAtA[i] = 0x12 + } + if len(x.ApplicationAddr) > 0 { + i -= len(x.ApplicationAddr) + copy(dAtA[i:], x.ApplicationAddr) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.ApplicationAddr))) + 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().(*EventApplicationReimbursementRequest) + 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: EventApplicationReimbursementRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: EventApplicationReimbursementRequest: 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 ApplicationAddr", 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.ApplicationAddr = 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 ServiceId", 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.ServiceId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field SessionId", 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.SessionId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Amount", 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.Amount == nil { + x.Amount = &v1beta1.Coin{} + } + if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.Amount); err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := runtime.Skip(dAtA[iNdEx:]) + if err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if !options.DiscardUnknown { + x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + } + iNdEx += skippy + } + } + + if iNdEx > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil + } + return &protoiface.Methods{ + NoUnkeyedLiterals: struct{}{}, + Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, + Size: size, + Marshal: marshal, + Unmarshal: unmarshal, + Merge: nil, + CheckInitialized: nil, + } +} + // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.0 @@ -3386,6 +4013,67 @@ func (x *EventSupplierSlashed) GetSlashingAmount() *v1beta1.Coin { return nil } +// EventApplicationReimbursementRequest is emitted when an application requests +// a reimbursement +type EventApplicationReimbursementRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ApplicationAddr string `protobuf:"bytes,1,opt,name=application_addr,json=applicationAddr,proto3" json:"application_addr,omitempty"` + ServiceId string `protobuf:"bytes,2,opt,name=service_id,json=serviceId,proto3" json:"service_id,omitempty"` + SessionId string `protobuf:"bytes,3,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` + Amount *v1beta1.Coin `protobuf:"bytes,4,opt,name=amount,proto3" json:"amount,omitempty"` +} + +func (x *EventApplicationReimbursementRequest) Reset() { + *x = EventApplicationReimbursementRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_poktroll_tokenomics_event_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EventApplicationReimbursementRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EventApplicationReimbursementRequest) ProtoMessage() {} + +// Deprecated: Use EventApplicationReimbursementRequest.ProtoReflect.Descriptor instead. +func (*EventApplicationReimbursementRequest) Descriptor() ([]byte, []int) { + return file_poktroll_tokenomics_event_proto_rawDescGZIP(), []int{5} +} + +func (x *EventApplicationReimbursementRequest) GetApplicationAddr() string { + if x != nil { + return x.ApplicationAddr + } + return "" +} + +func (x *EventApplicationReimbursementRequest) GetServiceId() string { + if x != nil { + return x.ServiceId + } + return "" +} + +func (x *EventApplicationReimbursementRequest) GetSessionId() string { + if x != nil { + return x.SessionId + } + return "" +} + +func (x *EventApplicationReimbursementRequest) GetAmount() *v1beta1.Coin { + if x != nil { + return x.Amount + } + return nil +} + var File_poktroll_tokenomics_event_proto protoreflect.FileDescriptor var file_poktroll_tokenomics_event_proto_rawDesc = []byte{ @@ -3481,26 +4169,38 @@ var file_poktroll_tokenomics_event_proto_rawDesc = []byte{ 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x0e, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, - 0x6e, 0x67, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x2a, 0x60, 0x0a, 0x15, 0x43, 0x6c, 0x61, 0x69, - 0x6d, 0x45, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x61, 0x73, 0x6f, - 0x6e, 0x12, 0x21, 0x0a, 0x1d, 0x45, 0x58, 0x50, 0x49, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, - 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, - 0x45, 0x44, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x4d, 0x49, - 0x53, 0x53, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x52, 0x4f, 0x4f, 0x46, - 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x02, 0x42, 0xbc, 0x01, 0xd8, 0xe2, 0x1e, - 0x01, 0x0a, 0x17, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2e, - 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0x42, 0x0a, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x24, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, - 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x6f, 0x6b, 0x74, 0x72, - 0x6f, 0x6c, 0x6c, 0x2f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0xa2, 0x02, - 0x03, 0x50, 0x54, 0x58, 0xaa, 0x02, 0x13, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2e, - 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0xca, 0x02, 0x13, 0x50, 0x6f, 0x6b, - 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x5c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, - 0xe2, 0x02, 0x1f, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x5c, 0x54, 0x6f, 0x6b, 0x65, - 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0xea, 0x02, 0x14, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x3a, 0x3a, 0x54, - 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x6e, 0x67, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xc2, 0x01, 0x0a, 0x24, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x69, + 0x6d, 0x62, 0x75, 0x72, 0x73, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x29, 0x0a, 0x10, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x61, 0x70, 0x70, + 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x12, 0x1d, 0x0a, 0x0a, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x31, 0x0a, 0x06, 0x61, 0x6d, + 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, + 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x2a, 0x60, 0x0a, + 0x15, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x45, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x1d, 0x45, 0x58, 0x50, 0x49, 0x52, 0x41, + 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, + 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x52, 0x4f, + 0x4f, 0x46, 0x5f, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, + 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x02, 0x42, + 0xbc, 0x01, 0xd8, 0xe2, 0x1e, 0x01, 0x0a, 0x17, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, 0x6b, 0x74, + 0x72, 0x6f, 0x6c, 0x6c, 0x2e, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0x42, + 0x0a, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x24, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, + 0x70, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, + 0x69, 0x63, 0x73, 0xa2, 0x02, 0x03, 0x50, 0x54, 0x58, 0xaa, 0x02, 0x13, 0x50, 0x6f, 0x6b, 0x74, + 0x72, 0x6f, 0x6c, 0x6c, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0xca, + 0x02, 0x13, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x5c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, + 0x6f, 0x6d, 0x69, 0x63, 0x73, 0xe2, 0x02, 0x1f, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, + 0x5c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x14, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, + 0x6c, 0x6c, 0x3a, 0x3a, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -3516,31 +4216,33 @@ func file_poktroll_tokenomics_event_proto_rawDescGZIP() []byte { } var file_poktroll_tokenomics_event_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_poktroll_tokenomics_event_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_poktroll_tokenomics_event_proto_msgTypes = make([]protoimpl.MessageInfo, 6) var file_poktroll_tokenomics_event_proto_goTypes = []interface{}{ - (ClaimExpirationReason)(0), // 0: poktroll.tokenomics.ClaimExpirationReason - (*EventClaimExpired)(nil), // 1: poktroll.tokenomics.EventClaimExpired - (*EventClaimSettled)(nil), // 2: poktroll.tokenomics.EventClaimSettled - (*EventRelayMiningDifficultyUpdated)(nil), // 3: poktroll.tokenomics.EventRelayMiningDifficultyUpdated - (*EventApplicationOverserviced)(nil), // 4: poktroll.tokenomics.EventApplicationOverserviced - (*EventSupplierSlashed)(nil), // 5: poktroll.tokenomics.EventSupplierSlashed - (*proof.Claim)(nil), // 6: poktroll.proof.Claim - (proof.ProofRequirementReason)(0), // 7: poktroll.proof.ProofRequirementReason - (*v1beta1.Coin)(nil), // 8: cosmos.base.v1beta1.Coin + (ClaimExpirationReason)(0), // 0: poktroll.tokenomics.ClaimExpirationReason + (*EventClaimExpired)(nil), // 1: poktroll.tokenomics.EventClaimExpired + (*EventClaimSettled)(nil), // 2: poktroll.tokenomics.EventClaimSettled + (*EventRelayMiningDifficultyUpdated)(nil), // 3: poktroll.tokenomics.EventRelayMiningDifficultyUpdated + (*EventApplicationOverserviced)(nil), // 4: poktroll.tokenomics.EventApplicationOverserviced + (*EventSupplierSlashed)(nil), // 5: poktroll.tokenomics.EventSupplierSlashed + (*EventApplicationReimbursementRequest)(nil), // 6: poktroll.tokenomics.EventApplicationReimbursementRequest + (*proof.Claim)(nil), // 7: poktroll.proof.Claim + (proof.ProofRequirementReason)(0), // 8: poktroll.proof.ProofRequirementReason + (*v1beta1.Coin)(nil), // 9: cosmos.base.v1beta1.Coin } var file_poktroll_tokenomics_event_proto_depIdxs = []int32{ - 6, // 0: poktroll.tokenomics.EventClaimExpired.claim:type_name -> poktroll.proof.Claim + 7, // 0: poktroll.tokenomics.EventClaimExpired.claim:type_name -> poktroll.proof.Claim 0, // 1: poktroll.tokenomics.EventClaimExpired.expiration_reason:type_name -> poktroll.tokenomics.ClaimExpirationReason - 6, // 2: poktroll.tokenomics.EventClaimSettled.claim:type_name -> poktroll.proof.Claim - 7, // 3: poktroll.tokenomics.EventClaimSettled.proof_requirement:type_name -> poktroll.proof.ProofRequirementReason - 8, // 4: poktroll.tokenomics.EventApplicationOverserviced.expected_burn:type_name -> cosmos.base.v1beta1.Coin - 8, // 5: poktroll.tokenomics.EventApplicationOverserviced.effective_burn:type_name -> cosmos.base.v1beta1.Coin - 8, // 6: poktroll.tokenomics.EventSupplierSlashed.slashing_amount:type_name -> cosmos.base.v1beta1.Coin - 7, // [7:7] is the sub-list for method output_type - 7, // [7:7] 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 + 7, // 2: poktroll.tokenomics.EventClaimSettled.claim:type_name -> poktroll.proof.Claim + 8, // 3: poktroll.tokenomics.EventClaimSettled.proof_requirement:type_name -> poktroll.proof.ProofRequirementReason + 9, // 4: poktroll.tokenomics.EventApplicationOverserviced.expected_burn:type_name -> cosmos.base.v1beta1.Coin + 9, // 5: poktroll.tokenomics.EventApplicationOverserviced.effective_burn:type_name -> cosmos.base.v1beta1.Coin + 9, // 6: poktroll.tokenomics.EventSupplierSlashed.slashing_amount:type_name -> cosmos.base.v1beta1.Coin + 9, // 7: poktroll.tokenomics.EventApplicationReimbursementRequest.amount:type_name -> cosmos.base.v1beta1.Coin + 8, // [8:8] is the sub-list for method output_type + 8, // [8:8] is the sub-list for method input_type + 8, // [8:8] is the sub-list for extension type_name + 8, // [8:8] is the sub-list for extension extendee + 0, // [0:8] is the sub-list for field type_name } func init() { file_poktroll_tokenomics_event_proto_init() } @@ -3609,6 +4311,18 @@ func file_poktroll_tokenomics_event_proto_init() { return nil } } + file_poktroll_tokenomics_event_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EventApplicationReimbursementRequest); 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{ @@ -3616,7 +4330,7 @@ func file_poktroll_tokenomics_event_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_poktroll_tokenomics_event_proto_rawDesc, NumEnums: 1, - NumMessages: 5, + NumMessages: 6, NumExtensions: 0, NumServices: 0, }, diff --git a/proto/poktroll/tokenomics/event.proto b/proto/poktroll/tokenomics/event.proto index 4c6f319b5..5f80f4525 100644 --- a/proto/poktroll/tokenomics/event.proto +++ b/proto/poktroll/tokenomics/event.proto @@ -70,4 +70,13 @@ message EventSupplierSlashed { // Amount slashed from the supplier's stake due to the expired claims. // This is a function of the number of expired claims and proof missing penalty. cosmos.base.v1beta1.Coin slashing_amount = 3; +} + +// EventApplicationReimbursementRequest is emitted when an application requests +// a reimbursement +message EventApplicationReimbursementRequest { + string application_addr = 1; + string service_id = 2; + string session_id = 3; + cosmos.base.v1beta1.Coin amount = 4; } \ No newline at end of file diff --git a/x/tokenomics/keeper/token_logic_modules.go b/x/tokenomics/keeper/token_logic_modules.go index 0dfe69d39..333f88a5e 100644 --- a/x/tokenomics/keeper/token_logic_modules.go +++ b/x/tokenomics/keeper/token_logic_modules.go @@ -68,11 +68,20 @@ const ( // global governance parameters in order to reward the participants providing // services while keeping inflation in check. TLMGlobalMint + + // TLMGlobalMintReimbursementRequest is the token logic module that complements + // TLMGlobalMint to enable permissionless demand. + // In order to prevent self-dealing attacks, applications will be overcharged by + // the amount equal to global inflation, those funds will be sent to the DAO/PNF, + // and an event will be emitted to track and send reimbursements; managed offchain by PNF. + // TODO_POST_MAINNET: Introduce proper tokenomics based on the research done by @rawthil and @shane. + TLMGlobalMintReimbursementRequest ) var tokenLogicModuleStrings = [...]string{ "TLMRelayBurnEqualsMint", "TLMGlobalMint", + "TLMGlobalMintReimbursementRequest", } func (tlm TokenLogicModule) String() string { @@ -317,10 +326,11 @@ func (k Keeper) TokenLogicModuleRelayBurnEqualsMint( // Update the application's on-chain stake newAppStake, err := application.Stake.SafeSub(actualSettlementCoin) if err != nil { - return tokenomicstypes.ErrTokenomicsApplicationNewStakeInvalid.Wrapf("application %q stake cannot be reduced to a negative amount %v", application.Address, newAppStake) + amountDiffCoin := actualSettlementCoin.Amount.Sub(application.Stake.Amount) + return tokenomicstypes.ErrTokenomicsApplicationNewStakeInvalid.Wrapf("application %q stake cannot be reduced to a negative amount -%s", application.Address, amountDiffCoin) } application.Stake = &newAppStake - logger.Info(fmt.Sprintf("updated application %q stake to %v", application.Address, newAppStake)) + logger.Info(fmt.Sprintf("updated application %q stake to %s", application.Address, newAppStake)) // Burn uPOKT from the application module account which was held in escrow // on behalf of the application account. @@ -329,7 +339,7 @@ func (k Keeper) TokenLogicModuleRelayBurnEqualsMint( ); err != nil { return tokenomicstypes.ErrTokenomicsApplicationModuleBurn.Wrapf("burning %s from the application module account: %v", actualSettlementCoin, err) } - logger.Info(fmt.Sprintf("burned (%v) from the application module account", actualSettlementCoin)) + logger.Info(fmt.Sprintf("burned (%s) from the application module account", actualSettlementCoin)) // Mint new uPOKT to the supplier module account. // These funds will be transferred to the supplier's shareholders below. @@ -448,6 +458,89 @@ func (k Keeper) TokenLogicModuleGlobalMint( return nil } +// TokenLogicModuleGlobalMintReimbursementRequest processes the business logic +// for the GlobalMintReimbursementRequest TLM. +func (k Keeper) TokenLogicModuleGlobalMintReimbursementRequest( + ctx context.Context, + service *sharedtypes.Service, + sessionHeader *sessiontypes.SessionHeader, + application *apptypes.Application, + supplier *sharedtypes.Supplier, + actualSettlementCoin cosmostypes.Coin, + relayMiningDifficulty *tokenomictypes.RelayMiningDifficulty, +) error { + logger := k.Logger().With("method", "TokenLogicModuleGlobalMintReimbursementRequest") + + // Determine how much new uPOKT to mint based on global inflation + newMintCoin, _ := calculateGlobalPerClaimMintInflationFromSettlementAmount(actualSettlementCoin) + if newMintCoin.Amount.Int64() == 0 { + return tokenomicstypes.ErrTokenomicsMintAmountZero + } + + // Update the application's on-chain stake + newAppStake, err := application.Stake.SafeSub(newMintCoin) + if err != nil { + amountDiffCoin := actualSettlementCoin.Amount.Sub(application.Stake.Amount) + return tokenomicstypes.ErrTokenomicsApplicationReimbursementRequestFailed.Wrapf( + "application %q stake cannot be reduced to a negative amount -%s", + application.Address, amountDiffCoin, + ) + } + application.Stake = &newAppStake + logger.Info(fmt.Sprintf("updated application %q stake to %s", application.Address, newAppStake)) + + // Send the global per claim mint inflation uPOKT from the application module + // account to the tokenomics module account. + if err := k.bankKeeper.SendCoinsFromModuleToModule( + ctx, apptypes.ModuleName, tokenomicstypes.ModuleName, sdk.NewCoins(actualSettlementCoin), + ); err != nil { + return tokenomicstypes.ErrTokenomicsApplicationReimbursementRequestFailed.Wrapf( + "sending %s from the application module account to the tokenomics module account: %v", + actualSettlementCoin, err, + ) + } + logger.Info(fmt.Sprintf( + "sent (%s) from the application module account to the tokenomics module account", + actualSettlementCoin, + )) + + // Send the global per claim mint inflation uPOKT from the tokenomics module + // account to PNF/DAO. + daoAccountAddr, err := cosmostypes.AccAddressFromBech32(k.GetAuthority()) + if err != nil { + return tokenomictypes.ErrTokenomicsApplicationReimbursementRequestFailed.Wrapf( + "getting PNF/DAO address: %v", + err, + ) + } + if err := k.bankKeeper.SendCoinsFromModuleToAccount( + ctx, tokenomicstypes.ModuleName, daoAccountAddr, sdk.NewCoins(newMintCoin), + ); err != nil { + return tokenomicstypes.ErrTokenomicsApplicationReimbursementRequestFailed.Wrapf( + "sending %s from the tokenomics module account to the PNF/DAO account: %v", + newMintCoin, err, + ) + } + + // Prepare and emit the event for the application being overcharged. + reimbursementRequestEvent := &tokenomicstypes.EventApplicationReimbursementRequest{ + ApplicationAddr: application.Address, + ServiceId: service.Id, + SessionId: sessionHeader.SessionId, + Amount: &newMintCoin, + } + + eventManger := cosmostypes.UnwrapSDKContext(ctx).EventManager() + if err := eventManger.EmitTypedEvent(reimbursementRequestEvent); err != nil { + return tokenomicstypes.ErrTokenomicsEmittingEventFailed.Wrapf( + "error emitting event %v", + reimbursementRequestEvent, + ) + } + + return nil +} + func (k Keeper) ensureMintedCoinsAreDistributed( logger log.Logger, appCoin, supplierCoin, daoCoin, serviceCoin, proposerCoin, newMintCoin cosmostypes.Coin, @@ -537,13 +630,19 @@ func (k Keeper) ensureClaimAmountLimits( // settlement. Relay miners use the appStake at the beginning of a session to determine // the maximum amount they can claim. We need to somehow access and propagate this // value (via context?) so it is the same for all TLM processors for each claim. - // Note that this will also need to incorporate MintPerClaimGlobalInflation because - // applications are being overcharged by that amount in the meantime. Whatever the - // solution and implementation ends up being, make sure to KISS. + // Note that this also incorporates MintPerClaimGlobalInflation since applications + // are being overcharged by that amount and the funds are sent to the DAO/PNF + // before being reimbursed to the application in the future. appStake := application.GetStake() + // Global inflation per claim amount should be accounted for in the max claimable amount. + // The application should have this additional amount in its stake to account + // so it can be deducted and sent to the DAO/PNF. + globalInflationCoin, _ := calculateGlobalPerClaimMintInflationFromSettlementAmount(claimSettlementCoin) + maxCalibmableAmt := appStake.Amount.Quo(math.NewInt(sessionkeeper.NumSupplierPerSession)).Sub(globalInflationCoin.Amount) + // Determine the max claimable amount for the supplier based on the application's stake in this session. - maxClaimableCoin := sdk.NewCoin(volatile.DenomuPOKT, appStake.Amount.Quo(math.NewInt(sessionkeeper.NumSupplierPerSession))) + maxClaimableCoin := sdk.NewCoin(volatile.DenomuPOKT, maxCalibmableAmt) if maxClaimableCoin.Amount.GTE(claimSettlementCoin.Amount) { logger.Info(fmt.Sprintf("Claim by supplier %s IS WITHIN LIMITS of servicing application %s. Max claimable amount >= Claim amount: %v >= %v", diff --git a/x/tokenomics/types/errors.go b/x/tokenomics/types/errors.go index 05afa3e9e..f91b7ef84 100644 --- a/x/tokenomics/types/errors.go +++ b/x/tokenomics/types/errors.go @@ -32,9 +32,10 @@ var ( ErrTokenomicsSupplierModuleMintFailed = sdkerrors.Register(ModuleName, 1123, "failed to mint uPOKT to supplier module account") ErrTokenomicsSupplierOwnerAddressInvalid = sdkerrors.Register(ModuleName, 1124, "the supplier owner address in the claim is not a valid bech32 address") ErrTokenomicsSupplierRevShareFailed = sdkerrors.Register(ModuleName, 1125, "failed to send rev share to supplier shareholders") - ErrTokenomicsApplicationReimbursementRequestFailed = sdkerrors.Register(ModuleName, 1126, "failed to send application reimbursement request event") + ErrTokenomicsApplicationReimbursementRequestFailed = sdkerrors.Register(ModuleName, 1126, "failed to process application reimbursement request") ErrTokenomicsAmountMismatchTooLarge = sdkerrors.Register(ModuleName, 1127, "an unexpected amount mismatch occurred") ErrTokenomicsMintAmountZero = sdkerrors.Register(ModuleName, 1128, "mint amount cannot be zero") ErrTokenomicsTLMError = sdkerrors.Register(ModuleName, 1129, "failed to process TLM") ErrTokenomicsCalculation = sdkerrors.Register(ModuleName, 1130, "tokenomics calculation error") + ErrTokenomicsApplicationModuleSendFailed = sdkerrors.Register(ModuleName, 1131, "failed to send uPOKT from application module account") ) diff --git a/x/tokenomics/types/event.pb.go b/x/tokenomics/types/event.pb.go index 85e281f24..6d36d8183 100644 --- a/x/tokenomics/types/event.pb.go +++ b/x/tokenomics/types/event.pb.go @@ -396,6 +396,72 @@ func (m *EventSupplierSlashed) GetSlashingAmount() *types1.Coin { return nil } +// EventApplicationReimbursementRequest is emitted when an application requests +// a reimbursement +type EventApplicationReimbursementRequest struct { + ApplicationAddr string `protobuf:"bytes,1,opt,name=application_addr,json=applicationAddr,proto3" json:"application_addr,omitempty"` + ServiceId string `protobuf:"bytes,2,opt,name=service_id,json=serviceId,proto3" json:"service_id,omitempty"` + SessionId string `protobuf:"bytes,3,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` + Amount *types1.Coin `protobuf:"bytes,4,opt,name=amount,proto3" json:"amount,omitempty"` +} + +func (m *EventApplicationReimbursementRequest) Reset() { *m = EventApplicationReimbursementRequest{} } +func (m *EventApplicationReimbursementRequest) String() string { return proto.CompactTextString(m) } +func (*EventApplicationReimbursementRequest) ProtoMessage() {} +func (*EventApplicationReimbursementRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_a78874bbf91a58c7, []int{5} +} +func (m *EventApplicationReimbursementRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EventApplicationReimbursementRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *EventApplicationReimbursementRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_EventApplicationReimbursementRequest.Merge(m, src) +} +func (m *EventApplicationReimbursementRequest) XXX_Size() int { + return m.Size() +} +func (m *EventApplicationReimbursementRequest) XXX_DiscardUnknown() { + xxx_messageInfo_EventApplicationReimbursementRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_EventApplicationReimbursementRequest proto.InternalMessageInfo + +func (m *EventApplicationReimbursementRequest) GetApplicationAddr() string { + if m != nil { + return m.ApplicationAddr + } + return "" +} + +func (m *EventApplicationReimbursementRequest) GetServiceId() string { + if m != nil { + return m.ServiceId + } + return "" +} + +func (m *EventApplicationReimbursementRequest) GetSessionId() string { + if m != nil { + return m.SessionId + } + return "" +} + +func (m *EventApplicationReimbursementRequest) GetAmount() *types1.Coin { + if m != nil { + return m.Amount + } + return nil +} + func init() { proto.RegisterEnum("poktroll.tokenomics.ClaimExpirationReason", ClaimExpirationReason_name, ClaimExpirationReason_value) proto.RegisterType((*EventClaimExpired)(nil), "poktroll.tokenomics.EventClaimExpired") @@ -403,63 +469,67 @@ func init() { proto.RegisterType((*EventRelayMiningDifficultyUpdated)(nil), "poktroll.tokenomics.EventRelayMiningDifficultyUpdated") proto.RegisterType((*EventApplicationOverserviced)(nil), "poktroll.tokenomics.EventApplicationOverserviced") proto.RegisterType((*EventSupplierSlashed)(nil), "poktroll.tokenomics.EventSupplierSlashed") + proto.RegisterType((*EventApplicationReimbursementRequest)(nil), "poktroll.tokenomics.EventApplicationReimbursementRequest") } func init() { proto.RegisterFile("poktroll/tokenomics/event.proto", fileDescriptor_a78874bbf91a58c7) } var fileDescriptor_a78874bbf91a58c7 = []byte{ - // 809 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x55, 0xcf, 0x72, 0xdb, 0x44, - 0x18, 0x8f, 0xdc, 0x94, 0x19, 0x6f, 0x49, 0x62, 0x6f, 0x13, 0x30, 0xa1, 0x55, 0x52, 0x1f, 0x98, - 0x50, 0x88, 0x34, 0x4d, 0x19, 0x4e, 0x4c, 0x07, 0x3b, 0x51, 0xa9, 0x66, 0xa8, 0x1d, 0xe4, 0x86, - 0x61, 0xb8, 0x2c, 0x6b, 0xe9, 0xb3, 0xbd, 0x44, 0xda, 0x15, 0xab, 0x95, 0xe3, 0x1c, 0x79, 0x03, - 0x1e, 0x80, 0x17, 0xe0, 0xc0, 0x2b, 0x70, 0xe6, 0xd8, 0x63, 0x4f, 0x19, 0x26, 0xb9, 0xe5, 0x29, - 0x98, 0x5d, 0xc9, 0xb1, 0x71, 0x42, 0x73, 0xee, 0xc5, 0x5e, 0x7f, 0xdf, 0xef, 0xf7, 0xfd, 0xf9, - 0xc9, 0xfb, 0x13, 0xda, 0x4a, 0xc5, 0xb1, 0x92, 0x22, 0x8e, 0x5d, 0x25, 0x8e, 0x81, 0x8b, 0x84, - 0x85, 0x99, 0x0b, 0x63, 0xe0, 0xca, 0x49, 0xa5, 0x50, 0x02, 0xdf, 0x9f, 0x02, 0x9c, 0x19, 0x60, - 0xd3, 0x0e, 0x45, 0x96, 0x88, 0xcc, 0xed, 0xd3, 0x0c, 0xdc, 0xf1, 0x93, 0x3e, 0x28, 0xfa, 0xc4, - 0x0d, 0x05, 0xe3, 0x05, 0x69, 0x73, 0x7d, 0x28, 0x86, 0xc2, 0x1c, 0x5d, 0x7d, 0x2a, 0xa3, 0x9b, - 0x57, 0xbd, 0x52, 0x29, 0xc4, 0xc0, 0x55, 0xa7, 0x29, 0x64, 0x45, 0xae, 0xf9, 0x67, 0x05, 0xd5, - 0x3d, 0xdd, 0x76, 0x3f, 0xa6, 0x2c, 0xf1, 0x26, 0x29, 0x93, 0x10, 0xe1, 0x2f, 0xd1, 0xdd, 0x50, - 0xff, 0x6e, 0x58, 0xdb, 0xd6, 0xce, 0xbd, 0xbd, 0x0d, 0xe7, 0x6a, 0x18, 0x53, 0xc1, 0x31, 0xe0, - 0x76, 0xf5, 0xf2, 0x6c, 0xab, 0xc0, 0x05, 0xc5, 0x17, 0xde, 0x45, 0x88, 0xe7, 0x09, 0x91, 0x10, - 0xd3, 0xd3, 0xac, 0x51, 0xd9, 0xb6, 0x76, 0x96, 0xdb, 0xab, 0x97, 0x67, 0x5b, 0x73, 0xd1, 0xa0, - 0xca, 0xf3, 0x24, 0x30, 0x47, 0xdc, 0x42, 0x75, 0x9d, 0x08, 0x45, 0x92, 0xe6, 0x0a, 0x48, 0xce, - 0x99, 0xca, 0x1a, 0x77, 0x0c, 0x6b, 0xe3, 0xf2, 0x6c, 0xeb, 0x7a, 0x32, 0x58, 0xe3, 0x79, 0xb2, - 0x5f, 0x44, 0x8e, 0x74, 0x00, 0x73, 0x54, 0x07, 0x3d, 0x34, 0x55, 0x4c, 0x70, 0x22, 0x81, 0x66, - 0x82, 0x37, 0x96, 0xb7, 0xad, 0x9d, 0xd5, 0xbd, 0xc7, 0xce, 0x0d, 0x12, 0x3a, 0xb3, 0x3d, 0x0d, - 0x25, 0x30, 0x8c, 0xa2, 0xdd, 0xb5, 0x42, 0x41, 0x0d, 0x16, 0x80, 0xcd, 0x3f, 0xfe, 0xa3, 0x57, - 0x0f, 0x94, 0x8a, 0xdf, 0x29, 0xbd, 0x7e, 0x46, 0x75, 0x33, 0x12, 0x91, 0xf0, 0x4b, 0xce, 0x24, - 0x24, 0xc0, 0x55, 0xa9, 0xd7, 0x27, 0x8b, 0x53, 0x1f, 0xea, 0xcf, 0x60, 0x86, 0x9b, 0xd7, 0xea, - 0x5a, 0x91, 0xa0, 0x96, 0x2e, 0xc0, 0x9b, 0xbf, 0x57, 0xd0, 0x23, 0xa3, 0x95, 0x19, 0xff, 0x25, - 0xe3, 0x8c, 0x0f, 0x0f, 0xd8, 0x60, 0xc0, 0xc2, 0x3c, 0x56, 0xa7, 0x47, 0x69, 0x44, 0x15, 0x44, - 0xf8, 0x21, 0x42, 0x19, 0xc8, 0x31, 0x0b, 0x81, 0xb0, 0xc8, 0x08, 0x58, 0x0d, 0xaa, 0x65, 0xc4, - 0x8f, 0xf0, 0x33, 0xf4, 0x20, 0x95, 0x30, 0x26, 0x8a, 0xca, 0x21, 0x28, 0x32, 0xa2, 0xd9, 0x88, - 0x8c, 0x60, 0x42, 0x80, 0x87, 0x22, 0x82, 0xc8, 0x88, 0x56, 0x0d, 0x1a, 0x1a, 0xf3, 0xca, 0x40, - 0x5e, 0xd0, 0x6c, 0xf4, 0x02, 0x26, 0x5e, 0x91, 0xc7, 0x5f, 0xa1, 0x8f, 0x39, 0x9c, 0xfc, 0x2f, - 0xfd, 0x8e, 0xa1, 0x7f, 0xc8, 0xe1, 0xe4, 0x46, 0xf6, 0x2e, 0xba, 0x6f, 0xba, 0xcf, 0x9e, 0x07, - 0x81, 0x84, 0x1a, 0xc1, 0x96, 0xf5, 0xc6, 0x30, 0xee, 0x4c, 0x9f, 0x8e, 0x97, 0x50, 0xfc, 0x19, - 0xc2, 0xba, 0xd9, 0x02, 0xfa, 0xae, 0x41, 0xaf, 0x71, 0x38, 0x99, 0x07, 0x37, 0x7f, 0xad, 0xa0, - 0x07, 0x46, 0x9e, 0x56, 0x9a, 0xc6, 0x2c, 0x34, 0xff, 0xb2, 0xee, 0x18, 0x64, 0xb9, 0x7b, 0x84, - 0x3f, 0x45, 0x35, 0x3a, 0x4b, 0x11, 0x1a, 0x45, 0xb2, 0xd4, 0x67, 0x6d, 0x2e, 0xde, 0x8a, 0x22, - 0x89, 0xbf, 0x40, 0x1f, 0x64, 0xb9, 0x8e, 0x81, 0x24, 0x22, 0x05, 0x49, 0x95, 0x90, 0x05, 0xa1, - 0xd0, 0x67, 0x7d, 0x9a, 0xed, 0x96, 0x49, 0xc3, 0x7a, 0x86, 0x56, 0x60, 0x92, 0x42, 0xa8, 0x20, - 0x22, 0xfd, 0x5c, 0x72, 0xa3, 0xc6, 0xbd, 0xbd, 0x8f, 0x9c, 0xc2, 0x66, 0x1c, 0x6d, 0x33, 0x4e, - 0x69, 0x33, 0xce, 0xbe, 0x60, 0x3c, 0x78, 0x7f, 0x8a, 0x6f, 0xe7, 0x92, 0xe3, 0xaf, 0xd1, 0x2a, - 0x0c, 0x06, 0x10, 0x2a, 0x36, 0x86, 0xa2, 0xc0, 0xf2, 0x6d, 0x05, 0x56, 0xae, 0x08, 0xba, 0x42, - 0xf3, 0x2f, 0x0b, 0xad, 0x1b, 0x0d, 0x7a, 0xe5, 0x7c, 0xbd, 0x98, 0x66, 0x23, 0x88, 0xde, 0xb2, - 0x90, 0xf5, 0x96, 0x85, 0x3e, 0x47, 0x58, 0x6b, 0x0f, 0x85, 0x8d, 0x11, 0x73, 0xc9, 0xca, 0x7b, - 0x15, 0xd4, 0x78, 0x3e, 0xf5, 0x37, 0x73, 0x1d, 0x33, 0xdc, 0x46, 0x6b, 0x99, 0x6e, 0xc7, 0xf8, - 0x90, 0xd0, 0x44, 0xe4, 0x5c, 0xdd, 0x2e, 0xc0, 0xea, 0x94, 0xd1, 0x32, 0x84, 0xc7, 0x3f, 0xa1, - 0x8d, 0x1b, 0x1d, 0x05, 0x3f, 0x42, 0x0f, 0xbd, 0x1f, 0x0e, 0xfd, 0xa0, 0xf5, 0xca, 0xef, 0x76, - 0x48, 0xe0, 0xb5, 0x7a, 0xdd, 0x0e, 0x39, 0xea, 0xf4, 0x0e, 0xbd, 0x7d, 0xff, 0xb9, 0xef, 0x1d, - 0xd4, 0x96, 0x70, 0x1d, 0xad, 0x1c, 0x06, 0xdd, 0xee, 0x73, 0xf2, 0xd2, 0xef, 0xf5, 0xfc, 0xce, - 0x37, 0x35, 0x6b, 0x16, 0xf2, 0x3b, 0xdf, 0xb7, 0xbe, 0xf5, 0x0f, 0x6a, 0x95, 0xf6, 0x77, 0x7f, - 0x9f, 0xdb, 0xd6, 0xeb, 0x73, 0xdb, 0x7a, 0x73, 0x6e, 0x5b, 0xff, 0x9c, 0xdb, 0xd6, 0x6f, 0x17, - 0xf6, 0xd2, 0xeb, 0x0b, 0x7b, 0xe9, 0xcd, 0x85, 0xbd, 0xf4, 0xe3, 0xd3, 0x21, 0x53, 0xa3, 0xbc, - 0xef, 0x84, 0x22, 0x71, 0xf5, 0xf5, 0xdd, 0xe5, 0xa0, 0x4e, 0x84, 0x3c, 0x76, 0xaf, 0x3c, 0x7f, - 0x32, 0xff, 0x86, 0x31, 0xd6, 0xdf, 0x7f, 0xcf, 0x78, 0xff, 0xd3, 0x7f, 0x03, 0x00, 0x00, 0xff, - 0xff, 0x69, 0x2d, 0x41, 0xba, 0x85, 0x06, 0x00, 0x00, + // 862 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x55, 0x4f, 0x6f, 0x1b, 0x45, + 0x14, 0xcf, 0xba, 0x69, 0x25, 0x4f, 0x49, 0x62, 0x4f, 0x13, 0x30, 0xa1, 0x75, 0x52, 0x0b, 0xa1, + 0x50, 0xc8, 0xae, 0x92, 0x22, 0x4e, 0xa8, 0xc2, 0x4e, 0x5c, 0xba, 0x12, 0xb5, 0xc3, 0xba, 0x41, + 0x88, 0xcb, 0x30, 0xde, 0x7d, 0xb6, 0x87, 0x78, 0x67, 0xb6, 0x33, 0xb3, 0x8e, 0x73, 0xe4, 0x1b, + 0xf0, 0x01, 0xf8, 0x02, 0x1c, 0xf8, 0x0a, 0x1c, 0x38, 0x71, 0xec, 0xb1, 0xa7, 0x08, 0x25, 0xb7, + 0x7c, 0x0a, 0x34, 0xb3, 0xeb, 0xd8, 0x75, 0x42, 0x23, 0x8e, 0xbd, 0x24, 0xe3, 0xf7, 0x7e, 0xbf, + 0xf7, 0xe7, 0x37, 0xfb, 0xde, 0xa0, 0x8d, 0x44, 0x1c, 0x69, 0x29, 0x86, 0x43, 0x4f, 0x8b, 0x23, + 0xe0, 0x22, 0x66, 0xa1, 0xf2, 0x60, 0x04, 0x5c, 0xbb, 0x89, 0x14, 0x5a, 0xe0, 0x7b, 0x13, 0x80, + 0x3b, 0x05, 0xac, 0x57, 0x43, 0xa1, 0x62, 0xa1, 0xbc, 0x2e, 0x55, 0xe0, 0x8d, 0x76, 0xba, 0xa0, + 0xe9, 0x8e, 0x17, 0x0a, 0xc6, 0x33, 0xd2, 0xfa, 0x6a, 0x5f, 0xf4, 0x85, 0x3d, 0x7a, 0xe6, 0x94, + 0x5b, 0xd7, 0x2f, 0x73, 0x25, 0x52, 0x88, 0x9e, 0xa7, 0x4f, 0x12, 0x50, 0x99, 0xaf, 0xf6, 0x47, + 0x01, 0x95, 0x9b, 0x26, 0xed, 0xde, 0x90, 0xb2, 0xb8, 0x39, 0x4e, 0x98, 0x84, 0x08, 0x7f, 0x89, + 0x6e, 0x87, 0xe6, 0x77, 0xc5, 0xd9, 0x74, 0xb6, 0xee, 0xee, 0xae, 0xb9, 0x97, 0xc5, 0xd8, 0x08, + 0xae, 0x05, 0x37, 0x8a, 0x17, 0xa7, 0x1b, 0x19, 0x2e, 0xc8, 0xfe, 0xe1, 0x6d, 0x84, 0x78, 0x1a, + 0x13, 0x09, 0x43, 0x7a, 0xa2, 0x2a, 0x85, 0x4d, 0x67, 0x6b, 0xb1, 0xb1, 0x7c, 0x71, 0xba, 0x31, + 0x63, 0x0d, 0x8a, 0x3c, 0x8d, 0x03, 0x7b, 0xc4, 0x75, 0x54, 0x36, 0x8e, 0x50, 0xc4, 0x49, 0xaa, + 0x81, 0xa4, 0x9c, 0x69, 0x55, 0xb9, 0x65, 0x59, 0x6b, 0x17, 0xa7, 0x1b, 0x57, 0x9d, 0xc1, 0x0a, + 0x4f, 0xe3, 0xbd, 0xcc, 0x72, 0x68, 0x0c, 0x98, 0xa3, 0x32, 0x98, 0xa2, 0xa9, 0x66, 0x82, 0x13, + 0x09, 0x54, 0x09, 0x5e, 0x59, 0xdc, 0x74, 0xb6, 0x96, 0x77, 0x1f, 0xb9, 0xd7, 0x48, 0xe8, 0x4e, + 0xfb, 0xb4, 0x94, 0xc0, 0x32, 0xb2, 0x74, 0x57, 0x02, 0x05, 0x25, 0x98, 0x03, 0xd6, 0x7e, 0x7f, + 0x43, 0xaf, 0x0e, 0x68, 0x3d, 0x7c, 0xa7, 0xf4, 0xfa, 0x19, 0x95, 0x6d, 0x49, 0x44, 0xc2, 0xcb, + 0x94, 0x49, 0x88, 0x81, 0xeb, 0x5c, 0xaf, 0x4f, 0xe6, 0xab, 0x3e, 0x30, 0x7f, 0x83, 0x29, 0x6e, + 0x56, 0xab, 0x2b, 0x41, 0x82, 0x52, 0x32, 0x07, 0xaf, 0xfd, 0x56, 0x40, 0x0f, 0xad, 0x56, 0xb6, + 0xfc, 0xe7, 0x8c, 0x33, 0xde, 0xdf, 0x67, 0xbd, 0x1e, 0x0b, 0xd3, 0xa1, 0x3e, 0x39, 0x4c, 0x22, + 0xaa, 0x21, 0xc2, 0x0f, 0x10, 0x52, 0x20, 0x47, 0x2c, 0x04, 0xc2, 0x22, 0x2b, 0x60, 0x31, 0x28, + 0xe6, 0x16, 0x3f, 0xc2, 0x4f, 0xd0, 0xfd, 0x44, 0xc2, 0x88, 0x68, 0x2a, 0xfb, 0xa0, 0xc9, 0x80, + 0xaa, 0x01, 0x19, 0xc0, 0x98, 0x00, 0x0f, 0x45, 0x04, 0x91, 0x15, 0xad, 0x18, 0x54, 0x0c, 0xe6, + 0x85, 0x85, 0x3c, 0xa3, 0x6a, 0xf0, 0x0c, 0xc6, 0xcd, 0xcc, 0x8f, 0xbf, 0x42, 0x1f, 0x71, 0x38, + 0xfe, 0x4f, 0xfa, 0x2d, 0x4b, 0xff, 0x80, 0xc3, 0xf1, 0xb5, 0xec, 0x6d, 0x74, 0xcf, 0x66, 0x9f, + 0xde, 0x07, 0x81, 0x98, 0x5a, 0xc1, 0x16, 0x4d, 0xc7, 0x30, 0x6a, 0x4d, 0x6e, 0xa7, 0x19, 0x53, + 0xfc, 0x19, 0xc2, 0x26, 0xd9, 0x1c, 0xfa, 0xb6, 0x45, 0xaf, 0x70, 0x38, 0x9e, 0x05, 0xd7, 0x7e, + 0x29, 0xa0, 0xfb, 0x56, 0x9e, 0x7a, 0x92, 0x0c, 0x59, 0x68, 0xbf, 0xb2, 0xf6, 0x08, 0x64, 0xde, + 0x7b, 0x84, 0x3f, 0x45, 0x25, 0x3a, 0x75, 0x11, 0x1a, 0x45, 0x32, 0xd7, 0x67, 0x65, 0xc6, 0x5e, + 0x8f, 0x22, 0x89, 0xbf, 0x40, 0xef, 0xab, 0xd4, 0xd8, 0x40, 0x12, 0x91, 0x80, 0xa4, 0x5a, 0xc8, + 0x8c, 0x90, 0xe9, 0xb3, 0x3a, 0xf1, 0xb6, 0x73, 0xa7, 0x65, 0x3d, 0x41, 0x4b, 0x30, 0x4e, 0x20, + 0xd4, 0x10, 0x91, 0x6e, 0x2a, 0xb9, 0x55, 0xe3, 0xee, 0xee, 0x87, 0x6e, 0xb6, 0x66, 0x5c, 0xb3, + 0x66, 0xdc, 0x7c, 0xcd, 0xb8, 0x7b, 0x82, 0xf1, 0xe0, 0xbd, 0x09, 0xbe, 0x91, 0x4a, 0x8e, 0xbf, + 0x46, 0xcb, 0xd0, 0xeb, 0x41, 0xa8, 0xd9, 0x08, 0xb2, 0x00, 0x8b, 0x37, 0x05, 0x58, 0xba, 0x24, + 0x98, 0x08, 0xb5, 0x3f, 0x1d, 0xb4, 0x6a, 0x35, 0xe8, 0xe4, 0xf5, 0x75, 0x86, 0x54, 0x0d, 0x20, + 0x7a, 0x4b, 0x43, 0xce, 0x5b, 0x1a, 0xfa, 0x1c, 0x61, 0xa3, 0x3d, 0x64, 0x6b, 0x8c, 0xd8, 0x21, + 0xcb, 0xe7, 0x2a, 0x28, 0xf1, 0x74, 0xb2, 0xdf, 0xec, 0x38, 0x2a, 0xdc, 0x40, 0x2b, 0xca, 0xa4, + 0x63, 0xbc, 0x4f, 0x68, 0x2c, 0x52, 0xae, 0x6f, 0x16, 0x60, 0x79, 0xc2, 0xa8, 0x5b, 0x42, 0xed, + 0x2f, 0x07, 0x7d, 0x3c, 0x7f, 0x89, 0x01, 0xb0, 0xb8, 0x9b, 0x4a, 0x95, 0x0f, 0xcd, 0xcb, 0x14, + 0x94, 0xfe, 0x3f, 0x97, 0xf9, 0xe6, 0x44, 0x14, 0xe6, 0x27, 0xc2, 0xba, 0x95, 0x32, 0x51, 0xd8, + 0xe4, 0x03, 0x2e, 0xe6, 0x16, 0x3f, 0xc2, 0x3b, 0xe8, 0x4e, 0xde, 0xcc, 0x8d, 0x97, 0x91, 0x03, + 0x1f, 0xfd, 0x84, 0xd6, 0xae, 0x5d, 0x8b, 0xf8, 0x21, 0x7a, 0xd0, 0xfc, 0xe1, 0xc0, 0x0f, 0xea, + 0x2f, 0xfc, 0x76, 0x8b, 0x04, 0xcd, 0x7a, 0xa7, 0xdd, 0x22, 0x87, 0xad, 0xce, 0x41, 0x73, 0xcf, + 0x7f, 0xea, 0x37, 0xf7, 0x4b, 0x0b, 0xb8, 0x8c, 0x96, 0x0e, 0x82, 0x76, 0xfb, 0x29, 0x79, 0xee, + 0x77, 0x3a, 0x7e, 0xeb, 0x9b, 0x92, 0x33, 0x35, 0xf9, 0xad, 0xef, 0xeb, 0xdf, 0xfa, 0xfb, 0xa5, + 0x42, 0xe3, 0xbb, 0xbf, 0xcf, 0xaa, 0xce, 0xab, 0xb3, 0xaa, 0xf3, 0xfa, 0xac, 0xea, 0xfc, 0x73, + 0x56, 0x75, 0x7e, 0x3d, 0xaf, 0x2e, 0xbc, 0x3a, 0xaf, 0x2e, 0xbc, 0x3e, 0xaf, 0x2e, 0xfc, 0xf8, + 0xb8, 0xcf, 0xf4, 0x20, 0xed, 0xba, 0xa1, 0x88, 0x3d, 0xb3, 0x83, 0xb6, 0x39, 0xe8, 0x63, 0x21, + 0x8f, 0xbc, 0xcb, 0x87, 0x6b, 0x3c, 0xfb, 0x4c, 0xda, 0xf7, 0xab, 0x7b, 0xc7, 0x3e, 0x60, 0x8f, + 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xea, 0x24, 0xad, 0x2e, 0x4a, 0x07, 0x00, 0x00, } func (m *EventClaimExpired) Marshal() (dAtA []byte, err error) { @@ -724,6 +794,62 @@ func (m *EventSupplierSlashed) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *EventApplicationReimbursementRequest) 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 *EventApplicationReimbursementRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventApplicationReimbursementRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Amount != nil { + { + size, err := m.Amount.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintEvent(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + if len(m.SessionId) > 0 { + i -= len(m.SessionId) + copy(dAtA[i:], m.SessionId) + i = encodeVarintEvent(dAtA, i, uint64(len(m.SessionId))) + i-- + dAtA[i] = 0x1a + } + if len(m.ServiceId) > 0 { + i -= len(m.ServiceId) + copy(dAtA[i:], m.ServiceId) + i = encodeVarintEvent(dAtA, i, uint64(len(m.ServiceId))) + i-- + dAtA[i] = 0x12 + } + if len(m.ApplicationAddr) > 0 { + i -= len(m.ApplicationAddr) + copy(dAtA[i:], m.ApplicationAddr) + i = encodeVarintEvent(dAtA, i, uint64(len(m.ApplicationAddr))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func encodeVarintEvent(dAtA []byte, offset int, v uint64) int { offset -= sovEvent(v) base := offset @@ -851,6 +977,31 @@ func (m *EventSupplierSlashed) Size() (n int) { return n } +func (m *EventApplicationReimbursementRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ApplicationAddr) + if l > 0 { + n += 1 + l + sovEvent(uint64(l)) + } + l = len(m.ServiceId) + if l > 0 { + n += 1 + l + sovEvent(uint64(l)) + } + l = len(m.SessionId) + if l > 0 { + n += 1 + l + sovEvent(uint64(l)) + } + if m.Amount != nil { + l = m.Amount.Size() + n += 1 + l + sovEvent(uint64(l)) + } + return n +} + func sovEvent(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -1650,6 +1801,188 @@ func (m *EventSupplierSlashed) Unmarshal(dAtA []byte) error { } return nil } +func (m *EventApplicationReimbursementRequest) 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 ErrIntOverflowEvent + } + 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: EventApplicationReimbursementRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventApplicationReimbursementRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ApplicationAddr", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + 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 ErrInvalidLengthEvent + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvent + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ApplicationAddr = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ServiceId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + 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 ErrInvalidLengthEvent + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvent + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ServiceId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SessionId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + 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 ErrInvalidLengthEvent + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvent + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SessionId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthEvent + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthEvent + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Amount == nil { + m.Amount = &types1.Coin{} + } + if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipEvent(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvent + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipEvent(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 From 1befc5e85c5d1cc2f7743978cac55ce1ce6cc727 Mon Sep 17 00:00:00 2001 From: Redouane Lakrache Date: Fri, 20 Sep 2024 23:03:46 +0200 Subject: [PATCH 17/31] fix: Skip GMRR if GMI is disabled --- x/tokenomics/keeper/token_logic_modules.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/x/tokenomics/keeper/token_logic_modules.go b/x/tokenomics/keeper/token_logic_modules.go index 333f88a5e..4536b0e7d 100644 --- a/x/tokenomics/keeper/token_logic_modules.go +++ b/x/tokenomics/keeper/token_logic_modules.go @@ -381,7 +381,6 @@ func (k Keeper) TokenLogicModuleGlobalMint( logger := k.Logger().With("method", "TokenLogicModuleGlobalMint") if MintPerClaimedTokenGlobalInflation == 0 { - // TODO_UPNEXT(@olshansk): Make sure to skip GMRR TLM in this case as well. logger.Warn("global inflation is set to zero. Skipping Global Mint TLM.") return nil } @@ -471,6 +470,11 @@ func (k Keeper) TokenLogicModuleGlobalMintReimbursementRequest( ) error { logger := k.Logger().With("method", "TokenLogicModuleGlobalMintReimbursementRequest") + if MintPerClaimedTokenGlobalInflation == 0 { + logger.Warn("global inflation is set to zero. Skipping Global Mint Reimbursement Request TLM.") + return nil + } + // Determine how much new uPOKT to mint based on global inflation newMintCoin, _ := calculateGlobalPerClaimMintInflationFromSettlementAmount(actualSettlementCoin) if newMintCoin.Amount.Int64() == 0 { @@ -491,7 +495,7 @@ func (k Keeper) TokenLogicModuleGlobalMintReimbursementRequest( // Send the global per claim mint inflation uPOKT from the application module // account to the tokenomics module account. - if err := k.bankKeeper.SendCoinsFromModuleToModule( + if err = k.bankKeeper.SendCoinsFromModuleToModule( ctx, apptypes.ModuleName, tokenomicstypes.ModuleName, sdk.NewCoins(actualSettlementCoin), ); err != nil { return tokenomicstypes.ErrTokenomicsApplicationReimbursementRequestFailed.Wrapf( From 197c5a0c69ca39bb60e24d05ee32d2f0cf4a2c4d Mon Sep 17 00:00:00 2001 From: Redouane Lakrache Date: Mon, 14 Oct 2024 12:12:10 +0200 Subject: [PATCH 18/31] fix: Activate GMRR TLM --- x/tokenomics/keeper/token_logic_modules.go | 31 +++++-------------- .../keeper/token_logic_modules_test.go | 10 +++++- 2 files changed, 16 insertions(+), 25 deletions(-) diff --git a/x/tokenomics/keeper/token_logic_modules.go b/x/tokenomics/keeper/token_logic_modules.go index a74f64d19..75af469ce 100644 --- a/x/tokenomics/keeper/token_logic_modules.go +++ b/x/tokenomics/keeper/token_logic_modules.go @@ -115,8 +115,9 @@ type TokenLogicModuleProcessor func( // tokenLogicModuleProcessorMap is a map of TLMs to their respective independent processors. var tokenLogicModuleProcessorMap = map[TokenLogicModule]TokenLogicModuleProcessor{ - TLMRelayBurnEqualsMint: Keeper.TokenLogicModuleRelayBurnEqualsMint, - TLMGlobalMint: Keeper.TokenLogicModuleGlobalMint, + TLMRelayBurnEqualsMint: Keeper.TokenLogicModuleRelayBurnEqualsMint, + TLMGlobalMint: Keeper.TokenLogicModuleGlobalMint, + TLMGlobalMintReimbursementRequest: Keeper.TokenLogicModuleGlobalMintReimbursementRequest, } func init() { @@ -332,24 +333,6 @@ func (k Keeper) TokenLogicModuleRelayBurnEqualsMint( // order economic effects with more optionality. This could include funds // going to pnf, delegators, enabling bonuses/rebates, etc... - // Update the application's on-chain stake - newAppStake, err := application.Stake.SafeSub(settlementCoin) - if err != nil { - amountDiffCoin := settlementCoin.Amount.Sub(application.Stake.Amount) - return tokenomicstypes.ErrTokenomicsApplicationNewStakeInvalid.Wrapf("application %q stake cannot be reduced to a negative amount -%s", application.Address, amountDiffCoin) - } - application.Stake = &newAppStake - logger.Info(fmt.Sprintf("updated application %q stake to %s", application.Address, newAppStake)) - - // Burn uPOKT from the application module account which was held in escrow - // on behalf of the application account. - if err := k.bankKeeper.BurnCoins( - ctx, apptypes.ModuleName, sdk.NewCoins(settlementCoin), - ); err != nil { - return tokenomicstypes.ErrTokenomicsApplicationModuleBurn.Wrapf("burning %s from the application module account: %v", settlementCoin, err) - } - logger.Info(fmt.Sprintf("burned (%s) from the application module account", settlementCoin)) - // Mint new uPOKT to the supplier module account. // These funds will be transferred to the supplier's shareholders below. // For reference, see operate/configs/supplier_staking_config.md. @@ -384,7 +367,7 @@ func (k Keeper) TokenLogicModuleRelayBurnEqualsMint( logger.Info(fmt.Sprintf("burned (%v) from the application module account", settlementCoin)) // Update the application's on-chain stake - newAppStake, err = application.Stake.SafeSub(settlementCoin) + newAppStake, err := application.Stake.SafeSub(settlementCoin) if err != nil { return tokenomicstypes.ErrTokenomicsApplicationNewStakeInvalid.Wrapf("application %q stake cannot be reduced to a negative amount %v", application.Address, newAppStake) } @@ -495,6 +478,7 @@ func (k Keeper) TokenLogicModuleGlobalMintReimbursementRequest( ) error { logger := k.Logger().With("method", "TokenLogicModuleGlobalMintReimbursementRequest") + // Do not process the reimbursement request if there is no global inflation. if MintPerClaimedTokenGlobalInflation == 0 { logger.Warn("global inflation is set to zero. Skipping Global Mint Reimbursement Request TLM.") return nil @@ -664,9 +648,8 @@ func (k Keeper) ensureClaimAmountLimits( // before being reimbursed to the application in the future. appStake := application.GetStake() - // Global inflation per claim amount should be accounted for in the max claimable amount. - // The application should have this additional amount in its stake to account - // so it can be deducted and sent to the DAO/PNF. + // The application should have enough stake to cover for the global mint reimbursement. + // This amount is deducted from the maximum claimable amount. globalInflationCoin, _ := calculateGlobalPerClaimMintInflationFromSettlementAmount(claimSettlementCoin) maxCalibmableAmt := appStake.Amount.Quo(math.NewInt(sessionkeeper.NumSupplierPerSession)).Sub(globalInflationCoin.Amount) diff --git a/x/tokenomics/keeper/token_logic_modules_test.go b/x/tokenomics/keeper/token_logic_modules_test.go index 812090ae7..df5c7a84c 100644 --- a/x/tokenomics/keeper/token_logic_modules_test.go +++ b/x/tokenomics/keeper/token_logic_modules_test.go @@ -400,6 +400,7 @@ func TestProcessTokenLogicModules_TLMGlobalMint_Valid_MintDistributionCorrect(t // Compute mint per actor numTokensMinted := numTokensClaimed * tokenomicskeeper.MintPerClaimedTokenGlobalInflation + numTokensMintedInt := math.NewIntFromUint64(uint64(numTokensMinted)) daoMint := math.NewInt(int64(numTokensMinted * tokenomicskeeper.MintAllocationDAO)) propMint := math.NewInt(int64(numTokensMinted * tokenomicskeeper.MintAllocationProposer)) serviceOwnerMint := math.NewInt(int64(numTokensMinted * tokenomicskeeper.MintAllocationSourceOwner)) @@ -407,7 +408,7 @@ func TestProcessTokenLogicModules_TLMGlobalMint_Valid_MintDistributionCorrect(t supplierMint := float32(numTokensMinted * tokenomicskeeper.MintAllocationSupplier) // Ensure the balance was increase be the appropriate amount - require.Equal(t, daoBalanceBefore.Amount.Add(daoMint), daoBalanceAfter.Amount) + require.Equal(t, daoBalanceBefore.Amount.Add(daoMint).Add(numTokensMintedInt), daoBalanceAfter.Amount) require.Equal(t, propBalanceBefore.Amount.Add(propMint), propBalanceAfter.Amount) require.Equal(t, serviceOwnerBalanceBefore.Amount.Add(serviceOwnerMint), serviceOwnerBalanceAfter.Amount) require.Equal(t, appBalanceBefore.Amount.Add(appMint), appBalanceAfter.Amount) @@ -423,6 +424,13 @@ func TestProcessTokenLogicModules_TLMGlobalMint_Valid_MintDistributionCorrect(t acceptableRoundingDelta := tokenomicskeeper.MintDistributionAllowableTolerancePercent * float64(balanceAfter) require.InDelta(t, expectedBalanceAfter, balanceAfter, acceptableRoundingDelta) } + + foundApp, appFound := keepers.GetApplication(ctx, appAddress) + require.True(t, appFound) + + appStakeAfter := foundApp.GetStake().Amount + numTokensClaimedInt := math.NewIntFromUint64(uint64(numTokensClaimed)) + require.Equal(t, appInitialStake.Sub(numTokensMintedInt).Sub(numTokensClaimedInt), appStakeAfter) } func TestProcessTokenLogicModules_AppNotFound(t *testing.T) { From 61a62fa4c5d1ed57e5e5a0c5ad3310405e77a40f Mon Sep 17 00:00:00 2001 From: Redouane Lakrache Date: Mon, 14 Oct 2024 12:14:35 +0200 Subject: [PATCH 19/31] chore: Add TODO for the relay miner to account for GMRR --- x/tokenomics/keeper/token_logic_modules.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x/tokenomics/keeper/token_logic_modules.go b/x/tokenomics/keeper/token_logic_modules.go index 75af469ce..577be76fb 100644 --- a/x/tokenomics/keeper/token_logic_modules.go +++ b/x/tokenomics/keeper/token_logic_modules.go @@ -650,6 +650,8 @@ func (k Keeper) ensureClaimAmountLimits( // The application should have enough stake to cover for the global mint reimbursement. // This amount is deducted from the maximum claimable amount. + // TODO_BETA(red-0ne): Make sure that the relay miner logic also accounts for this + // when deciding to serve an application. globalInflationCoin, _ := calculateGlobalPerClaimMintInflationFromSettlementAmount(claimSettlementCoin) maxCalibmableAmt := appStake.Amount.Quo(math.NewInt(sessionkeeper.NumSupplierPerSession)).Sub(globalInflationCoin.Amount) From 13784b880fef8da335dbd502c467b6e74d5a6af3 Mon Sep 17 00:00:00 2001 From: Redouane Lakrache Date: Mon, 14 Oct 2024 15:22:01 +0200 Subject: [PATCH 20/31] fix: Min stake tests --- .../integration/application/min_stake_test.go | 18 ++++++++++++++---- testutil/keeper/tokenomics.go | 3 +++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/tests/integration/application/min_stake_test.go b/tests/integration/application/min_stake_test.go index 0815dba96..d7a0c1683 100644 --- a/tests/integration/application/min_stake_test.go +++ b/tests/integration/application/min_stake_test.go @@ -2,10 +2,11 @@ package application import ( "context" + "math" "testing" cosmoslog "cosmossdk.io/log" - "cosmossdk.io/math" + sdkmath "cosmossdk.io/math" cosmostypes "github.com/cosmos/cosmos-sdk/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/stretchr/testify/require" @@ -22,6 +23,7 @@ import ( sessiontypes "github.com/pokt-network/poktroll/x/session/types" "github.com/pokt-network/poktroll/x/shared" sharedtypes "github.com/pokt-network/poktroll/x/shared/types" + tokenomicskeeper "github.com/pokt-network/poktroll/x/tokenomics/keeper" ) type applicationMinStakeTestSuite struct { @@ -83,6 +85,12 @@ func (s *applicationMinStakeTestSuite) TestAppIsUnbondedIfBelowMinStakeWhenSettl // Stake a supplier for service 1. s.stakeSupplier() + proofParams := s.keepers.ProofKeeper.GetParams(s.ctx) + proofParams.ProofRequestProbability = 0 + proofRequirementThreshold := cosmostypes.NewInt64Coin(volatile.DenomuPOKT, math.MaxInt64) + proofParams.ProofRequirementThreshold = &proofRequirementThreshold + s.keepers.ProofKeeper.SetParams(s.ctx, proofParams) + // Get the session header. sessionHeader := s.getSessionHeader() @@ -107,9 +115,11 @@ func (s *applicationMinStakeTestSuite) TestAppIsUnbondedIfBelowMinStakeWhenSettl _, isAppFound := s.keepers.ApplicationKeeper.GetApplication(s.ctx, s.appBech32) require.False(s.T(), isAppFound) - // Assert that the application's stake was returned to its bank balance. - expectedAppBurn := math.NewInt(int64(s.numRelays * s.numComputeUnitsPerRelay * sharedtypes.DefaultComputeUnitsToTokensMultiplier)) - expectedAppBalance := s.appStake.SubAmount(expectedAppBurn) + // Assert that the remaining application's stake was returned to its bank balance. + expectedAppBurn := sdkmath.NewInt(int64(s.numRelays * s.numComputeUnitsPerRelay * sharedtypes.DefaultComputeUnitsToTokensMultiplier)) + globalInflationAmount := float64(expectedAppBurn.Uint64()) * tokenomicskeeper.MintPerClaimedTokenGlobalInflation + globalInflationAmountInt := sdkmath.NewInt(int64(globalInflationAmount)) + expectedAppBalance := s.appStake.SubAmount(expectedAppBurn).SubAmount(globalInflationAmountInt) appBalance = s.getAppBalance() require.Equal(s.T(), expectedAppBalance.Amount.Int64(), appBalance.Amount.Int64()) diff --git a/testutil/keeper/tokenomics.go b/testutil/keeper/tokenomics.go index f9df12788..98e95bc96 100644 --- a/testutil/keeper/tokenomics.go +++ b/testutil/keeper/tokenomics.go @@ -195,6 +195,9 @@ func TokenomicsKeeperWithActorAddrs(t testing.TB) ( mockBankKeeper.EXPECT(). SendCoinsFromModuleToModule(gomock.Any(), tokenomicstypes.ModuleName, suppliertypes.ModuleName, gomock.Any()). AnyTimes() + mockBankKeeper.EXPECT(). + SendCoinsFromModuleToModule(gomock.Any(), apptypes.ModuleName, tokenomicstypes.ModuleName, gomock.Any()). + AnyTimes() // Mock the account keeper mockAccountKeeper := mocks.NewMockAccountKeeper(ctrl) From e91a20ebfd76a806accf90a173c1a833b0f44f6d Mon Sep 17 00:00:00 2001 From: Redouane Lakrache Date: Fri, 18 Oct 2024 15:10:30 +0200 Subject: [PATCH 21/31] feat: Add WithProofRequirement option --- api/poktroll/supplier/tx.pulsar.go | 2 +- .../integration/application/min_stake_test.go | 9 +---- .../relay_mining_integration_test.go | 9 +---- testutil/keeper/tokenomics.go | 33 ++++++++++++++++--- x/tokenomics/keeper/token_logic_modules.go | 29 ++++++++++++++-- x/tokenomics/types/expected_keepers.go | 1 + x/tokenomics/types/tx.pb.go | 1 - 7 files changed, 59 insertions(+), 25 deletions(-) diff --git a/api/poktroll/supplier/tx.pulsar.go b/api/poktroll/supplier/tx.pulsar.go index 7a709f7f0..1d2057b01 100644 --- a/api/poktroll/supplier/tx.pulsar.go +++ b/api/poktroll/supplier/tx.pulsar.go @@ -5,11 +5,11 @@ import ( _ "cosmossdk.io/api/amino" v1beta1 "cosmossdk.io/api/cosmos/base/v1beta1" _ "cosmossdk.io/api/cosmos/msg/v1" + shared "github.com/pokt-network/poktroll/api/poktroll/shared" fmt "fmt" _ "github.com/cosmos/cosmos-proto" runtime "github.com/cosmos/cosmos-proto/runtime" _ "github.com/cosmos/gogoproto/gogoproto" - shared "github.com/pokt-network/poktroll/api/poktroll/shared" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoiface "google.golang.org/protobuf/runtime/protoiface" protoimpl "google.golang.org/protobuf/runtime/protoimpl" diff --git a/tests/integration/application/min_stake_test.go b/tests/integration/application/min_stake_test.go index b05eb907a..c0f2f3d14 100644 --- a/tests/integration/application/min_stake_test.go +++ b/tests/integration/application/min_stake_test.go @@ -2,7 +2,6 @@ package application import ( "context" - "math" "testing" cosmoslog "cosmossdk.io/log" @@ -48,7 +47,7 @@ func TestApplicationMinStakeTestSuite(t *testing.T) { } func (s *applicationMinStakeTestSuite) SetupTest() { - s.keepers, s.ctx = keeper.NewTokenomicsModuleKeepers(s.T(), cosmoslog.NewNopLogger()) + s.keepers, s.ctx = keeper.NewTokenomicsModuleKeepers(s.T(), cosmoslog.NewNopLogger(), keeper.WithProofRequirement(false)) proofParams := prooftypes.DefaultParams() proofParams.ProofRequestProbability = 0 @@ -84,12 +83,6 @@ func (s *applicationMinStakeTestSuite) TestAppIsUnbondedIfBelowMinStakeWhenSettl // Stake a supplier for service 1. s.stakeSupplier() - proofParams := s.keepers.ProofKeeper.GetParams(s.ctx) - proofParams.ProofRequestProbability = 0 - proofRequirementThreshold := cosmostypes.NewInt64Coin(volatile.DenomuPOKT, math.MaxInt64) - proofParams.ProofRequirementThreshold = &proofRequirementThreshold - s.keepers.ProofKeeper.SetParams(s.ctx, proofParams) - // Get the session header. sessionHeader := s.getSessionHeader() diff --git a/tests/integration/tokenomics/relay_mining_integration_test.go b/tests/integration/tokenomics/relay_mining_integration_test.go index 2beeb2196..b97dc4b15 100644 --- a/tests/integration/tokenomics/relay_mining_integration_test.go +++ b/tests/integration/tokenomics/relay_mining_integration_test.go @@ -1,7 +1,6 @@ package integration_test import ( - "math" "math/big" "testing" @@ -84,6 +83,7 @@ func TestComputeNewDifficultyHash_RewardsReflectWorkCompleted(t *testing.T) { testutils.WithService(service), testutils.WithApplication(application), testutils.WithSupplier(supplier), + testutils.WithProofRequirement(false), ) sdkCtx := sdk.UnwrapSDKContext(ctx) sdkCtx = sdkCtx.WithBlockHeight(1) @@ -94,13 +94,6 @@ func TestComputeNewDifficultyHash_RewardsReflectWorkCompleted(t *testing.T) { err := keepers.SharedKeeper.SetParams(sdkCtx, sharedParams) require.NoError(t, err) - // Set the global proof params so we never need a proof (for simplicity of this test) - err = keepers.ProofKeeper.SetParams(sdkCtx, prooftypes.Params{ - ProofRequestProbability: 0, // we never need a proof randomly - ProofRequirementThreshold: &sdk.Coin{Denom: volatile.DenomuPOKT, Amount: sdkmath.NewInt(math.MaxInt64)}, // a VERY high threshold - }) - require.NoError(t, err) - // Update the relay mining difficulty so there's always a difficulty to retrieve // for the test service. _, err = keepers.ServiceKeeper.UpdateRelayMiningDifficulty(sdkCtx, map[string]uint64{service.Id: 1}) diff --git a/testutil/keeper/tokenomics.go b/testutil/keeper/tokenomics.go index 98e95bc96..31083c757 100644 --- a/testutil/keeper/tokenomics.go +++ b/testutil/keeper/tokenomics.go @@ -2,10 +2,11 @@ package keeper import ( "context" + "math" "testing" "cosmossdk.io/log" - "cosmossdk.io/math" + sdkmath "cosmossdk.io/math" "cosmossdk.io/store" "cosmossdk.io/store/metrics" storetypes "cosmossdk.io/store/types" @@ -29,6 +30,7 @@ import ( "github.com/stretchr/testify/require" "github.com/pokt-network/poktroll/app" + "github.com/pokt-network/poktroll/app/volatile" "github.com/pokt-network/poktroll/testutil/sample" "github.com/pokt-network/poktroll/testutil/tokenomics/mocks" appkeeper "github.com/pokt-network/poktroll/x/application/keeper" @@ -117,7 +119,7 @@ func TokenomicsKeeperWithActorAddrs(t testing.TB) ( // Prepare the test application. application := apptypes.Application{ Address: sample.AccAddress(), - Stake: &sdk.Coin{Denom: "upokt", Amount: math.NewInt(100000)}, + Stake: &sdk.Coin{Denom: "upokt", Amount: sdkmath.NewInt(100000)}, ServiceConfigs: []*sharedtypes.ApplicationServiceConfig{{ServiceId: service.Id}}, } @@ -126,7 +128,7 @@ func TokenomicsKeeperWithActorAddrs(t testing.TB) ( supplier := sharedtypes.Supplier{ OwnerAddress: supplierOwnerAddr, OperatorAddress: supplierOwnerAddr, - Stake: &sdk.Coin{Denom: "upokt", Amount: math.NewInt(100000)}, + Stake: &sdk.Coin{Denom: "upokt", Amount: sdkmath.NewInt(100000)}, Services: []*sharedtypes.SupplierServiceConfig{ { ServiceId: service.Id, @@ -345,9 +347,9 @@ func NewTokenomicsModuleKeepers( require.NoError(t, bankKeeper.SetParams(sdkCtx, banktypes.DefaultParams())) // Provide some initial funds to the suppliers & applications module accounts. - err = bankKeeper.MintCoins(sdkCtx, suppliertypes.ModuleName, sdk.NewCoins(sdk.NewCoin("upokt", math.NewInt(1000000000000)))) + err = bankKeeper.MintCoins(sdkCtx, suppliertypes.ModuleName, sdk.NewCoins(sdk.NewCoin("upokt", sdkmath.NewInt(1000000000000)))) require.NoError(t, err) - err = bankKeeper.MintCoins(sdkCtx, apptypes.ModuleName, sdk.NewCoins(sdk.NewCoin("upokt", math.NewInt(1000000000000)))) + err = bankKeeper.MintCoins(sdkCtx, apptypes.ModuleName, sdk.NewCoins(sdk.NewCoin("upokt", sdkmath.NewInt(1000000000000)))) require.NoError(t, err) // Construct a real shared keeper. @@ -511,3 +513,24 @@ func WithProposerAddr(addr string) TokenomicsModuleKeepersOpt { return sdkCtx } } + +// WithProofRequirement is an option to set the proof requirement in the tokenomics module keepers. +func WithProofRequirement(required bool) TokenomicsModuleKeepersOpt { + return func(ctx context.Context, keepers *TokenomicsModuleKeepers) context.Context { + + proofParams := keepers.ProofKeeper.GetParams(ctx) + if required { + proofParams.ProofRequestProbability = 1 + proofRequirementThreshold := cosmostypes.NewInt64Coin(volatile.DenomuPOKT, 0) + proofParams.ProofRequirementThreshold = &proofRequirementThreshold + } else { + proofParams.ProofRequestProbability = 0 + proofRequirementThreshold := cosmostypes.NewInt64Coin(volatile.DenomuPOKT, math.MaxInt64) + proofParams.ProofRequirementThreshold = &proofRequirementThreshold + } + + keepers.ProofKeeper.SetParams(ctx, proofParams) + + return ctx + } +} diff --git a/x/tokenomics/keeper/token_logic_modules.go b/x/tokenomics/keeper/token_logic_modules.go index 1f2bd1d84..b4ed4339b 100644 --- a/x/tokenomics/keeper/token_logic_modules.go +++ b/x/tokenomics/keeper/token_logic_modules.go @@ -660,13 +660,38 @@ func (k Keeper) ensureClaimAmountLimits( // before being reimbursed to the application in the future. appStake := application.GetStake() - // The application should have enough stake to cover for the global mint reimbursement. - // This amount is deducted from the maximum claimable amount. // TODO_BETA(red-0ne): Make sure that the relay miner logic also accounts for this // when deciding to serve an application. + + // The application should have enough stake to cover for the global mint reimbursement. + // This amount is deducted from the maximum claimable amount. globalInflationCoin, _ := calculateGlobalPerClaimMintInflationFromSettlementAmount(claimSettlementCoin) + + // TODO_BETA(@red-0ne): Introduce a session sliding window to account for potential consumption + // during the current session (i.e. Not the session being settled) such as: + // maxCalibmableAmt = (AppStake / (currSessNum - settlingSessNum + 1) / NumSuppliersPerSession) - GlobalInflation + // In conjunction with single service applications, this would make maxClaimableAmt + // effectively addressing the issue of over-servicing. + // Example: + // - Current session num: 3 + // - Settling session num: 2 + // - Application already requested work for session 3 + // Problem: + // - If the application consumes its entire stake in settlement of session 2 + // - Then over-servicing in session 3 (i.e. No stake left to consume) + // Solution: + // - By dividing the claimable stake by 2 (3 - 2 + 1), settling session 2 assumes that + // the application will consume its maxClaimableAmt the current session (3). + // - Off-chain actors could use this formula during the servicing of session num 3 + // and assume maxClaimableAmt will be settled in session 2. + // - Garantee no over-servicing at the cost of higher application stake requirements. maxCalibmableAmt := appStake.Amount.Quo(math.NewInt(sessionkeeper.NumSupplierPerSession)).Sub(globalInflationCoin.Amount) + if !maxCalibmableAmt.IsPositive() { + // TODO_CONSIDERATION: Should we stop processing if the app stake is not ehnough? + logger.Warn(fmt.Sprintf("Application %s stake (%s) cannot cover the global inflation %s", application.GetAddress(), appStake, globalInflationCoin)) + } + // Determine the max claimable amount for the supplier based on the application's stake in this session. maxClaimableCoin := sdk.NewCoin(volatile.DenomuPOKT, maxCalibmableAmt) diff --git a/x/tokenomics/types/expected_keepers.go b/x/tokenomics/types/expected_keepers.go index 6d198a320..ea1771845 100644 --- a/x/tokenomics/types/expected_keepers.go +++ b/x/tokenomics/types/expected_keepers.go @@ -45,6 +45,7 @@ type ApplicationKeeper interface { SetApplication(ctx context.Context, app apptypes.Application) GetAllApplications(ctx context.Context) []apptypes.Application UnbondApplication(ctx context.Context, app *apptypes.Application) error + GetParams(ctx context.Context) apptypes.Params } type ProofKeeper interface { diff --git a/x/tokenomics/types/tx.pb.go b/x/tokenomics/types/tx.pb.go index e4fec264c..9f18a148c 100644 --- a/x/tokenomics/types/tx.pb.go +++ b/x/tokenomics/types/tx.pb.go @@ -125,7 +125,6 @@ type MsgUpdateParam struct { // specified in the `Params` message in `proof/params.proto.` Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` // Types that are valid to be assigned to AsType: - // // *MsgUpdateParam_AsString // *MsgUpdateParam_AsInt64 // *MsgUpdateParam_AsBytes From 568ecb9b9753c764c794e139725c25f800a70f6c Mon Sep 17 00:00:00 2001 From: Redouane Lakrache Date: Thu, 24 Oct 2024 21:28:00 +0200 Subject: [PATCH 22/31] fix: ensure app stake is always enough --- x/tokenomics/keeper/settle_pending_claims.go | 18 ++++- x/tokenomics/keeper/token_logic_modules.go | 79 +++++++++++++------- 2 files changed, 70 insertions(+), 27 deletions(-) diff --git a/x/tokenomics/keeper/settle_pending_claims.go b/x/tokenomics/keeper/settle_pending_claims.go index 88aea8965..094cae7c0 100644 --- a/x/tokenomics/keeper/settle_pending_claims.go +++ b/x/tokenomics/keeper/settle_pending_claims.go @@ -37,6 +37,19 @@ func (k Keeper) SettlePendingClaims(ctx sdk.Context) ( return settledResult, expiredResult, err } + // Capture the applications initial stake which will be used to calculate the + // max share any claim could receive from the application stake. + applicationInitialStakeMap := make(map[string]sdk.Coin) + for _, claim := range expiringClaims { + app, isAppFound := k.applicationKeeper.GetApplication(ctx, claim.SessionHeader.ApplicationAddress) + if !isAppFound { + err := apptypes.ErrAppNotFound.Wrapf("application address: %q", claim.SessionHeader.ApplicationAddress) + return settledResult, expiredResult, err + } + + applicationInitialStakeMap[claim.SessionHeader.ApplicationAddress] = *app.GetStake() + } + blockHeight := ctx.BlockHeight() logger.Info(fmt.Sprintf("found %d expiring claims at block height %d", len(expiringClaims), blockHeight)) @@ -178,8 +191,11 @@ func (k Keeper) SettlePendingClaims(ctx sdk.Context) ( // 1. The claim does not require a proof. // 2. The claim requires a proof and a valid proof was found. + claimApplication := claim.SessionHeader.ApplicationAddress + applicationInitialStake := applicationInitialStakeMap[claimApplication] + // Manage the mint & burn accounting for the claim. - if err = k.ProcessTokenLogicModules(ctx, &claim); err != nil { + if err = k.ProcessTokenLogicModules(ctx, &claim, applicationInitialStake); err != nil { logger.Error(fmt.Sprintf("error processing token logic modules for claim %q: %v", claim.SessionHeader.SessionId, err)) return settledResult, expiredResult, err } diff --git a/x/tokenomics/keeper/token_logic_modules.go b/x/tokenomics/keeper/token_logic_modules.go index b4ed4339b..0cd63e101 100644 --- a/x/tokenomics/keeper/token_logic_modules.go +++ b/x/tokenomics/keeper/token_logic_modules.go @@ -141,6 +141,7 @@ func init() { func (k Keeper) ProcessTokenLogicModules( ctx context.Context, claim *prooftypes.Claim, + applicationInitialStake cosmostypes.Coin, ) (err error) { logger := k.Logger().With("method", "ProcessTokenLogicModules") @@ -286,7 +287,7 @@ func (k Keeper) ProcessTokenLogicModules( // Ensure the claim amount is within the limits set by Relay Mining. // If not, update the settlement amount and emit relevant events. - actualSettlementCoin, err := k.ensureClaimAmountLimits(ctx, logger, &application, &supplier, claimSettlementCoin) + actualSettlementCoin, err := k.ensureClaimAmountLimits(ctx, logger, &application, &supplier, claimSettlementCoin, applicationInitialStake) if err != nil { return err } @@ -517,7 +518,7 @@ func (k Keeper) TokenLogicModuleGlobalMintReimbursementRequest( // Send the global per claim mint inflation uPOKT from the application module // account to the tokenomics module account. if err = k.bankKeeper.SendCoinsFromModuleToModule( - ctx, apptypes.ModuleName, tokenomicstypes.ModuleName, sdk.NewCoins(actualSettlementCoin), + ctx, apptypes.ModuleName, tokenomicstypes.ModuleName, sdk.NewCoins(newMintCoin), ); err != nil { return tokenomicstypes.ErrTokenomicsApplicationReimbursementRequestFailed.Wrapf( "sending %s from the application module account to the tokenomics module account: %v", @@ -644,6 +645,7 @@ func (k Keeper) ensureClaimAmountLimits( logger log.Logger, application *apptypes.Application, supplier *sharedtypes.Supplier, + initialApplicationStake cosmostypes.Coin, claimSettlementCoin cosmostypes.Coin, ) ( actualSettlementCoins cosmostypes.Coin, @@ -651,25 +653,22 @@ func (k Keeper) ensureClaimAmountLimits( ) { logger = logger.With("helper", "ensureClaimAmountLimits") - // TODO_BETA_OR_MAINNET(@red-0ne): The application stake gets reduced with every claim - // settlement. Relay miners use the appStake at the beginning of a session to determine - // the maximum amount they can claim. We need to somehow access and propagate this - // value (via context?) so it is the same for all TLM processors for each claim. + // TODO_BETA(@red-0ne): Make relay miners use the appStake at the beginning + // of a session to determine the maximum amount they can claim. // Note that this also incorporates MintPerClaimGlobalInflation since applications // are being overcharged by that amount and the funds are sent to the DAO/PNF // before being reimbursed to the application in the future. - appStake := application.GetStake() - - // TODO_BETA(red-0ne): Make sure that the relay miner logic also accounts for this - // when deciding to serve an application. + appStake := initialApplicationStake // The application should have enough stake to cover for the global mint reimbursement. // This amount is deducted from the maximum claimable amount. globalInflationCoin, _ := calculateGlobalPerClaimMintInflationFromSettlementAmount(claimSettlementCoin) + globalInflationAmt := globalInflationCoin.Amount + stakeRequirementAmt := claimSettlementCoin.Amount.Add(globalInflationAmt) // TODO_BETA(@red-0ne): Introduce a session sliding window to account for potential consumption // during the current session (i.e. Not the session being settled) such as: - // maxCalibmableAmt = (AppStake / (currSessNum - settlingSessNum + 1) / NumSuppliersPerSession) - GlobalInflation + // maxCalibmableAmt = (AppStake / (currSessNum - settlingSessNum + 1) / NumSuppliersPerSession) // In conjunction with single service applications, this would make maxClaimableAmt // effectively addressing the issue of over-servicing. // Example: @@ -685,33 +684,46 @@ func (k Keeper) ensureClaimAmountLimits( // - Off-chain actors could use this formula during the servicing of session num 3 // and assume maxClaimableAmt will be settled in session 2. // - Garantee no over-servicing at the cost of higher application stake requirements. - maxCalibmableAmt := appStake.Amount.Quo(math.NewInt(sessionkeeper.NumSupplierPerSession)).Sub(globalInflationCoin.Amount) + maxClaimableAmt := appStake.Amount.Quo(math.NewInt(sessionkeeper.NumSupplierPerSession)) + maxClaimSettlementAmt := stakeToMaxSettlementAmount(maxClaimableAmt) + + // Check if the claimable amount is capped by the max claimable amount. + if stakeRequirementAmt.GT(maxClaimableAmt) { + logger.Warn(fmt.Sprintf("Claim by supplier %s EXCEEDS LIMITS for application %s. Max claimable amount < Claim amount: %v < %v", + supplier.GetOperatorAddress(), application.GetAddress(), maxClaimableAmt, claimSettlementCoin.Amount)) - if !maxCalibmableAmt.IsPositive() { - // TODO_CONSIDERATION: Should we stop processing if the app stake is not ehnough? - logger.Warn(fmt.Sprintf("Application %s stake (%s) cannot cover the global inflation %s", application.GetAddress(), appStake, globalInflationCoin)) + stakeRequirementAmt = maxClaimableAmt + maxClaimSettlementAmt = stakeToMaxSettlementAmount(stakeRequirementAmt) + globalInflationAmt = stakeRequirementAmt.Sub(maxClaimSettlementAmt) } - // Determine the max claimable amount for the supplier based on the application's stake in this session. - maxClaimableCoin := sdk.NewCoin(volatile.DenomuPOKT, maxCalibmableAmt) + // Check if the claimable amount should be capped by an insufficient application stake. + if maxClaimableAmt.LT(stakeRequirementAmt) { + logger.Warn(fmt.Sprintf("Claim by supplier %q EXCEEDS application %q claimable stake. Claim amount > App claimable stake: %v > %v", + supplier.GetOperatorAddress(), application.GetAddress(), claimSettlementCoin, maxClaimableAmt)) + stakeRequirementAmt = maxClaimableAmt + maxClaimSettlementAmt = stakeToMaxSettlementAmount(stakeRequirementAmt) + globalInflationAmt = stakeRequirementAmt.Sub(maxClaimSettlementAmt) + } - if maxClaimableCoin.Amount.GTE(claimSettlementCoin.Amount) { + // Nominal case: The claimable amount is within the limits set by Relay Mining. + if claimSettlementCoin.Amount.LTE(maxClaimSettlementAmt) { logger.Info(fmt.Sprintf("Claim by supplier %s IS WITHIN LIMITS of servicing application %s. Max claimable amount >= Claim amount: %v >= %v", - supplier.GetOperatorAddress(), application.GetAddress(), maxClaimableCoin, claimSettlementCoin.Amount)) + supplier.GetOperatorAddress(), application.GetAddress(), maxClaimSettlementAmt, claimSettlementCoin.Amount)) return claimSettlementCoin, nil } - logger.Warn(fmt.Sprintf("Claim by supplier %s EXCEEDS LIMITS for application %s. Max claimable amount < Claim amount: %v < %v", - supplier.GetOperatorAddress(), application.GetAddress(), maxClaimableCoin, claimSettlementCoin.Amount)) + // Claimable amount is capped by the max claimable amount or the application allocated stake. + // Determine the max claimable amount for the supplier based on the application's stake in this session. + maxClaimableCoin := sdk.NewCoin(volatile.DenomuPOKT, maxClaimSettlementAmt) - // Reduce the settlement amount if the application was over-serviced - actualSettlementCoins = maxClaimableCoin + stakeRequirementCoin := sdk.NewCoin(volatile.DenomuPOKT, stakeRequirementAmt) // Prepare and emit the event for the application being overserviced applicationOverservicedEvent := &tokenomicstypes.EventApplicationOverserviced{ - ApplicationAddr: application.Address, + ApplicationAddr: application.GetAddress(), SupplierOperatorAddr: supplier.GetOperatorAddress(), - ExpectedBurn: &claimSettlementCoin, + ExpectedBurn: &stakeRequirementCoin, EffectiveBurn: &maxClaimableCoin, } eventManager := cosmostypes.UnwrapSDKContext(ctx).EventManager() @@ -720,7 +732,7 @@ func (k Keeper) ensureClaimAmountLimits( tokenomicstypes.ErrTokenomicsEmittingEventFailed.Wrapf("error emitting event %v", applicationOverservicedEvent) } - return actualSettlementCoins, nil + return maxClaimableCoin, nil } // distributeSupplierRewardsToShareHolders distributes the supplier rewards to its @@ -797,6 +809,21 @@ func calculateGlobalPerClaimMintInflationFromSettlementAmount(settlementCoin sdk return mintAmtCoin, *newMintAmtFloat } +// stakeToMaxSettlementAmount calculates the max amount of uPOKT to that the supplier +// can claim based on the stake share and the global inflation allocation percentage. +// This is the inverse of calculateGlobalPerClaimMintInflationFromSettlementAmount. +// stake = maxSettlementAmt + globalInflationAmt +// stake = maxSettlementAmt + (maxSettlementAmt * MintPerClaimedTokenGlobalInflation) +// stake = maxSettlementAmt * (1 + MintPerClaimedTokenGlobalInflation) +// maxSettlementAmt = stake / (1 + MintPerClaimedTokenGlobalInflation) +func stakeToMaxSettlementAmount(stakeShare math.Int) math.Int { + stakeSahreFloat := big.NewFloat(0).SetInt(stakeShare.BigInt()) + maxSettlementAmountFloat := big.NewFloat(0).Quo(stakeSahreFloat, big.NewFloat(1+MintPerClaimedTokenGlobalInflation)) + + settlementAmount, _ := maxSettlementAmountFloat.Int(nil) + return math.NewIntFromBigInt(settlementAmount) +} + // calculateAllocationAmount does big float arithmetic to determine the absolute // amount from amountFloat based on the allocation percentage provided. // TODO_MAINNET(@bryanchriswhite): Measure and limit the precision loss here. From 6c836e73adbc4110094d9ffea132b18563a51307 Mon Sep 17 00:00:00 2001 From: Redouane Lakrache Date: Thu, 24 Oct 2024 23:33:13 +0200 Subject: [PATCH 23/31] fix: Ensure no over-servicing --- api/poktroll/tokenomics/event.pulsar.go | 229 +++++++++++++++--- e2e/tests/0_settlement.feature | 6 +- proto/poktroll/tokenomics/event.proto | 8 +- testutil/keeper/tokenomics.go | 4 +- x/tokenomics/keeper/token_logic_modules.go | 39 ++- .../keeper/token_logic_modules_test.go | 17 +- x/tokenomics/types/event.pb.go | 222 ++++++++++++----- 7 files changed, 392 insertions(+), 133 deletions(-) diff --git a/api/poktroll/tokenomics/event.pulsar.go b/api/poktroll/tokenomics/event.pulsar.go index a4fe5e521..cf18db79d 100644 --- a/api/poktroll/tokenomics/event.pulsar.go +++ b/api/poktroll/tokenomics/event.pulsar.go @@ -2617,17 +2617,21 @@ func (x *fastReflection_EventSupplierSlashed) ProtoMethods() *protoiface.Methods } var ( - md_EventApplicationReimbursementRequest protoreflect.MessageDescriptor - fd_EventApplicationReimbursementRequest_application_addr protoreflect.FieldDescriptor - fd_EventApplicationReimbursementRequest_service_id protoreflect.FieldDescriptor - fd_EventApplicationReimbursementRequest_session_id protoreflect.FieldDescriptor - fd_EventApplicationReimbursementRequest_amount protoreflect.FieldDescriptor + md_EventApplicationReimbursementRequest protoreflect.MessageDescriptor + fd_EventApplicationReimbursementRequest_application_addr protoreflect.FieldDescriptor + fd_EventApplicationReimbursementRequest_supplier_operator_addr protoreflect.FieldDescriptor + fd_EventApplicationReimbursementRequest_supplier_owner_addr protoreflect.FieldDescriptor + fd_EventApplicationReimbursementRequest_service_id protoreflect.FieldDescriptor + fd_EventApplicationReimbursementRequest_session_id protoreflect.FieldDescriptor + fd_EventApplicationReimbursementRequest_amount protoreflect.FieldDescriptor ) func init() { file_poktroll_tokenomics_event_proto_init() md_EventApplicationReimbursementRequest = File_poktroll_tokenomics_event_proto.Messages().ByName("EventApplicationReimbursementRequest") fd_EventApplicationReimbursementRequest_application_addr = md_EventApplicationReimbursementRequest.Fields().ByName("application_addr") + fd_EventApplicationReimbursementRequest_supplier_operator_addr = md_EventApplicationReimbursementRequest.Fields().ByName("supplier_operator_addr") + fd_EventApplicationReimbursementRequest_supplier_owner_addr = md_EventApplicationReimbursementRequest.Fields().ByName("supplier_owner_addr") fd_EventApplicationReimbursementRequest_service_id = md_EventApplicationReimbursementRequest.Fields().ByName("service_id") fd_EventApplicationReimbursementRequest_session_id = md_EventApplicationReimbursementRequest.Fields().ByName("session_id") fd_EventApplicationReimbursementRequest_amount = md_EventApplicationReimbursementRequest.Fields().ByName("amount") @@ -2704,6 +2708,18 @@ func (x *fastReflection_EventApplicationReimbursementRequest) Range(f func(proto return } } + if x.SupplierOperatorAddr != "" { + value := protoreflect.ValueOfString(x.SupplierOperatorAddr) + if !f(fd_EventApplicationReimbursementRequest_supplier_operator_addr, value) { + return + } + } + if x.SupplierOwnerAddr != "" { + value := protoreflect.ValueOfString(x.SupplierOwnerAddr) + if !f(fd_EventApplicationReimbursementRequest_supplier_owner_addr, value) { + return + } + } if x.ServiceId != "" { value := protoreflect.ValueOfString(x.ServiceId) if !f(fd_EventApplicationReimbursementRequest_service_id, value) { @@ -2739,6 +2755,10 @@ func (x *fastReflection_EventApplicationReimbursementRequest) Has(fd protoreflec switch fd.FullName() { case "poktroll.tokenomics.EventApplicationReimbursementRequest.application_addr": return x.ApplicationAddr != "" + case "poktroll.tokenomics.EventApplicationReimbursementRequest.supplier_operator_addr": + return x.SupplierOperatorAddr != "" + case "poktroll.tokenomics.EventApplicationReimbursementRequest.supplier_owner_addr": + return x.SupplierOwnerAddr != "" case "poktroll.tokenomics.EventApplicationReimbursementRequest.service_id": return x.ServiceId != "" case "poktroll.tokenomics.EventApplicationReimbursementRequest.session_id": @@ -2763,6 +2783,10 @@ func (x *fastReflection_EventApplicationReimbursementRequest) Clear(fd protorefl switch fd.FullName() { case "poktroll.tokenomics.EventApplicationReimbursementRequest.application_addr": x.ApplicationAddr = "" + case "poktroll.tokenomics.EventApplicationReimbursementRequest.supplier_operator_addr": + x.SupplierOperatorAddr = "" + case "poktroll.tokenomics.EventApplicationReimbursementRequest.supplier_owner_addr": + x.SupplierOwnerAddr = "" case "poktroll.tokenomics.EventApplicationReimbursementRequest.service_id": x.ServiceId = "" case "poktroll.tokenomics.EventApplicationReimbursementRequest.session_id": @@ -2788,6 +2812,12 @@ func (x *fastReflection_EventApplicationReimbursementRequest) Get(descriptor pro case "poktroll.tokenomics.EventApplicationReimbursementRequest.application_addr": value := x.ApplicationAddr return protoreflect.ValueOfString(value) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.supplier_operator_addr": + value := x.SupplierOperatorAddr + return protoreflect.ValueOfString(value) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.supplier_owner_addr": + value := x.SupplierOwnerAddr + return protoreflect.ValueOfString(value) case "poktroll.tokenomics.EventApplicationReimbursementRequest.service_id": value := x.ServiceId return protoreflect.ValueOfString(value) @@ -2819,6 +2849,10 @@ func (x *fastReflection_EventApplicationReimbursementRequest) Set(fd protoreflec switch fd.FullName() { case "poktroll.tokenomics.EventApplicationReimbursementRequest.application_addr": x.ApplicationAddr = value.Interface().(string) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.supplier_operator_addr": + x.SupplierOperatorAddr = value.Interface().(string) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.supplier_owner_addr": + x.SupplierOwnerAddr = value.Interface().(string) case "poktroll.tokenomics.EventApplicationReimbursementRequest.service_id": x.ServiceId = value.Interface().(string) case "poktroll.tokenomics.EventApplicationReimbursementRequest.session_id": @@ -2852,6 +2886,10 @@ func (x *fastReflection_EventApplicationReimbursementRequest) Mutable(fd protore return protoreflect.ValueOfMessage(x.Amount.ProtoReflect()) case "poktroll.tokenomics.EventApplicationReimbursementRequest.application_addr": panic(fmt.Errorf("field application_addr of message poktroll.tokenomics.EventApplicationReimbursementRequest is not mutable")) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.supplier_operator_addr": + panic(fmt.Errorf("field supplier_operator_addr of message poktroll.tokenomics.EventApplicationReimbursementRequest is not mutable")) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.supplier_owner_addr": + panic(fmt.Errorf("field supplier_owner_addr of message poktroll.tokenomics.EventApplicationReimbursementRequest is not mutable")) case "poktroll.tokenomics.EventApplicationReimbursementRequest.service_id": panic(fmt.Errorf("field service_id of message poktroll.tokenomics.EventApplicationReimbursementRequest is not mutable")) case "poktroll.tokenomics.EventApplicationReimbursementRequest.session_id": @@ -2871,6 +2909,10 @@ func (x *fastReflection_EventApplicationReimbursementRequest) NewField(fd protor switch fd.FullName() { case "poktroll.tokenomics.EventApplicationReimbursementRequest.application_addr": return protoreflect.ValueOfString("") + case "poktroll.tokenomics.EventApplicationReimbursementRequest.supplier_operator_addr": + return protoreflect.ValueOfString("") + case "poktroll.tokenomics.EventApplicationReimbursementRequest.supplier_owner_addr": + return protoreflect.ValueOfString("") case "poktroll.tokenomics.EventApplicationReimbursementRequest.service_id": return protoreflect.ValueOfString("") case "poktroll.tokenomics.EventApplicationReimbursementRequest.session_id": @@ -2951,6 +2993,14 @@ func (x *fastReflection_EventApplicationReimbursementRequest) ProtoMethods() *pr if l > 0 { n += 1 + l + runtime.Sov(uint64(l)) } + l = len(x.SupplierOperatorAddr) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + l = len(x.SupplierOwnerAddr) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } l = len(x.ServiceId) if l > 0 { n += 1 + l + runtime.Sov(uint64(l)) @@ -3004,20 +3054,34 @@ func (x *fastReflection_EventApplicationReimbursementRequest) ProtoMethods() *pr copy(dAtA[i:], encoded) i = runtime.EncodeVarint(dAtA, i, uint64(len(encoded))) i-- - dAtA[i] = 0x22 + dAtA[i] = 0x32 } if len(x.SessionId) > 0 { i -= len(x.SessionId) copy(dAtA[i:], x.SessionId) i = runtime.EncodeVarint(dAtA, i, uint64(len(x.SessionId))) i-- - dAtA[i] = 0x1a + dAtA[i] = 0x2a } if len(x.ServiceId) > 0 { i -= len(x.ServiceId) copy(dAtA[i:], x.ServiceId) i = runtime.EncodeVarint(dAtA, i, uint64(len(x.ServiceId))) i-- + dAtA[i] = 0x22 + } + if len(x.SupplierOwnerAddr) > 0 { + i -= len(x.SupplierOwnerAddr) + copy(dAtA[i:], x.SupplierOwnerAddr) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.SupplierOwnerAddr))) + i-- + dAtA[i] = 0x1a + } + if len(x.SupplierOperatorAddr) > 0 { + i -= len(x.SupplierOperatorAddr) + copy(dAtA[i:], x.SupplierOperatorAddr) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.SupplierOperatorAddr))) + i-- dAtA[i] = 0x12 } if len(x.ApplicationAddr) > 0 { @@ -3109,6 +3173,70 @@ func (x *fastReflection_EventApplicationReimbursementRequest) ProtoMethods() *pr x.ApplicationAddr = 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 SupplierOperatorAddr", 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.SupplierOperatorAddr = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field SupplierOwnerAddr", 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.SupplierOwnerAddr = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: if wireType != 2 { return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field ServiceId", wireType) } @@ -3140,7 +3268,7 @@ func (x *fastReflection_EventApplicationReimbursementRequest) ProtoMethods() *pr } x.ServiceId = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 3: + case 5: if wireType != 2 { return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field SessionId", wireType) } @@ -3172,7 +3300,7 @@ func (x *fastReflection_EventApplicationReimbursementRequest) ProtoMethods() *pr } x.SessionId = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 4: + case 6: if wireType != 2 { return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) } @@ -3608,10 +3736,12 @@ type EventApplicationReimbursementRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - ApplicationAddr string `protobuf:"bytes,1,opt,name=application_addr,json=applicationAddr,proto3" json:"application_addr,omitempty"` - ServiceId string `protobuf:"bytes,2,opt,name=service_id,json=serviceId,proto3" json:"service_id,omitempty"` - SessionId string `protobuf:"bytes,3,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` - Amount *v1beta1.Coin `protobuf:"bytes,4,opt,name=amount,proto3" json:"amount,omitempty"` + ApplicationAddr string `protobuf:"bytes,1,opt,name=application_addr,json=applicationAddr,proto3" json:"application_addr,omitempty"` + SupplierOperatorAddr string `protobuf:"bytes,2,opt,name=supplier_operator_addr,json=supplierOperatorAddr,proto3" json:"supplier_operator_addr,omitempty"` + SupplierOwnerAddr string `protobuf:"bytes,3,opt,name=supplier_owner_addr,json=supplierOwnerAddr,proto3" json:"supplier_owner_addr,omitempty"` + ServiceId string `protobuf:"bytes,4,opt,name=service_id,json=serviceId,proto3" json:"service_id,omitempty"` + SessionId string `protobuf:"bytes,5,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` + Amount *v1beta1.Coin `protobuf:"bytes,6,opt,name=amount,proto3" json:"amount,omitempty"` } func (x *EventApplicationReimbursementRequest) Reset() { @@ -3641,6 +3771,20 @@ func (x *EventApplicationReimbursementRequest) GetApplicationAddr() string { return "" } +func (x *EventApplicationReimbursementRequest) GetSupplierOperatorAddr() string { + if x != nil { + return x.SupplierOperatorAddr + } + return "" +} + +func (x *EventApplicationReimbursementRequest) GetSupplierOwnerAddr() string { + if x != nil { + return x.SupplierOwnerAddr + } + return "" +} + func (x *EventApplicationReimbursementRequest) GetServiceId() string { if x != nil { return x.ServiceId @@ -3764,38 +3908,45 @@ var file_poktroll_tokenomics_event_proto_rawDesc = []byte{ 0x73, 0x68, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x0e, 0x73, - 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xc2, 0x01, + 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xa8, 0x02, 0x0a, 0x24, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x69, 0x6d, 0x62, 0x75, 0x72, 0x73, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x64, 0x64, - 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, - 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, - 0x31, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, - 0x6e, 0x74, 0x2a, 0x60, 0x0a, 0x15, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x45, 0x78, 0x70, 0x69, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x1d, 0x45, - 0x58, 0x50, 0x49, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, - 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x11, - 0x0a, 0x0d, 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4e, 0x47, 0x10, - 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, - 0x49, 0x44, 0x10, 0x02, 0x42, 0xbc, 0x01, 0xd8, 0xe2, 0x1e, 0x01, 0x0a, 0x17, 0x63, 0x6f, 0x6d, - 0x2e, 0x70, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2e, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, - 0x6d, 0x69, 0x63, 0x73, 0x42, 0x0a, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x50, 0x01, 0x5a, 0x24, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, - 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2f, 0x74, 0x6f, - 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0xa2, 0x02, 0x03, 0x50, 0x54, 0x58, 0xaa, 0x02, - 0x13, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, - 0x6d, 0x69, 0x63, 0x73, 0xca, 0x02, 0x13, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x5c, - 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0xe2, 0x02, 0x1f, 0x50, 0x6f, 0x6b, + 0x72, 0x12, 0x34, 0x0a, 0x16, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x5f, 0x6f, 0x70, + 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x14, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x4f, 0x70, 0x65, 0x72, 0x61, + 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x12, 0x2e, 0x0a, 0x13, 0x73, 0x75, 0x70, 0x70, 0x6c, + 0x69, 0x65, 0x72, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x4f, 0x77, + 0x6e, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x31, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, + 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, + 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x2a, 0x60, 0x0a, 0x15, 0x43, 0x6c, 0x61, 0x69, + 0x6d, 0x45, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x61, 0x73, 0x6f, + 0x6e, 0x12, 0x21, 0x0a, 0x1d, 0x45, 0x58, 0x50, 0x49, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, + 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, + 0x45, 0x44, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x4d, 0x49, + 0x53, 0x53, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x52, 0x4f, 0x4f, 0x46, + 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x02, 0x42, 0xbc, 0x01, 0xd8, 0xe2, 0x1e, + 0x01, 0x0a, 0x17, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2e, + 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0x42, 0x0a, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x24, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, + 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x6f, 0x6b, 0x74, 0x72, + 0x6f, 0x6c, 0x6c, 0x2f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0xa2, 0x02, + 0x03, 0x50, 0x54, 0x58, 0xaa, 0x02, 0x13, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2e, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0xca, 0x02, 0x13, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x5c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, - 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x14, 0x50, - 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x3a, 0x3a, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, - 0x69, 0x63, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0xe2, 0x02, 0x1f, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x5c, 0x54, 0x6f, 0x6b, 0x65, + 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0xea, 0x02, 0x14, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x3a, 0x3a, 0x54, + 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( diff --git a/e2e/tests/0_settlement.feature b/e2e/tests/0_settlement.feature index 0fe804d5a..26ae94691 100644 --- a/e2e/tests/0_settlement.feature +++ b/e2e/tests/0_settlement.feature @@ -38,7 +38,8 @@ Feature: Tokenomics Namespace # TODO_TECHDEBT: Update this test such the inflation is set and enforce that Mint=Burn # Then add a separate test that only validates that inflation is enforced correctly Then the account balance of "supplier1" should be "898" uPOKT "more" than before - And the "application" stake of "app1" should be "840" uPOKT "less" than before + # The application stake should be less 840 * (1 + glbal_inflation) = 840 * 1.1 = 924 + And the "application" stake of "app1" should be "924" uPOKT "less" than before Scenario: TLM Mint=Burn when a valid claim is create but not required # Baseline @@ -72,7 +73,8 @@ Feature: Tokenomics Namespace # Please note that supplier mint is > app burn because of inflation # TODO_TECHDEBT: Update this test such the inflation is set and enforce that Mint=Burn Then the account balance of "supplier1" should be "449" uPOKT "more" than before - And the "application" stake of "app1" should be "420" uPOKT "less" than before + # The application stake should be less 420 * (1 + glbal_inflation) = 420 * 1.1 = 462 + And the "application" stake of "app1" should be "462" uPOKT "less" than before # TODO_ADDTEST: Implement the following scenarios # Scenario: Supplier revenue shares are properly distributed diff --git a/proto/poktroll/tokenomics/event.proto b/proto/poktroll/tokenomics/event.proto index f75a8324c..c3751c60d 100644 --- a/proto/poktroll/tokenomics/event.proto +++ b/proto/poktroll/tokenomics/event.proto @@ -85,7 +85,9 @@ message EventSupplierSlashed { // a reimbursement message EventApplicationReimbursementRequest { string application_addr = 1; - string service_id = 2; - string session_id = 3; - cosmos.base.v1beta1.Coin amount = 4; + string supplier_operator_addr = 2; + string supplier_owner_addr = 3; + string service_id = 4; + string session_id = 5; + cosmos.base.v1beta1.Coin amount = 6; } \ No newline at end of file diff --git a/testutil/keeper/tokenomics.go b/testutil/keeper/tokenomics.go index 31083c757..79d3cb828 100644 --- a/testutil/keeper/tokenomics.go +++ b/testutil/keeper/tokenomics.go @@ -529,7 +529,9 @@ func WithProofRequirement(required bool) TokenomicsModuleKeepersOpt { proofParams.ProofRequirementThreshold = &proofRequirementThreshold } - keepers.ProofKeeper.SetParams(ctx, proofParams) + if err := keepers.ProofKeeper.SetParams(ctx, proofParams); err != nil { + panic(err) + } return ctx } diff --git a/x/tokenomics/keeper/token_logic_modules.go b/x/tokenomics/keeper/token_logic_modules.go index 0cd63e101..1d9ae4446 100644 --- a/x/tokenomics/keeper/token_logic_modules.go +++ b/x/tokenomics/keeper/token_logic_modules.go @@ -504,20 +504,16 @@ func (k Keeper) TokenLogicModuleGlobalMintReimbursementRequest( } // Update the application's on-chain stake - newAppStake, err := application.Stake.SafeSub(newMintCoin) - if err != nil { - amountDiffCoin := actualSettlementCoin.Amount.Sub(application.Stake.Amount) - return tokenomicstypes.ErrTokenomicsApplicationReimbursementRequestFailed.Wrapf( - "application %q stake cannot be reduced to a negative amount -%s", - application.Address, amountDiffCoin, - ) - } + // This should not fall below zero since `ensureClaimAmountLimits` should have + // already checked and adjusted the settlement amount so that the application + // stake covers the global inflation. + newAppStake := application.Stake.Sub(newMintCoin) application.Stake = &newAppStake logger.Info(fmt.Sprintf("updated application %q stake to %s", application.Address, newAppStake)) // Send the global per claim mint inflation uPOKT from the application module // account to the tokenomics module account. - if err = k.bankKeeper.SendCoinsFromModuleToModule( + if err := k.bankKeeper.SendCoinsFromModuleToModule( ctx, apptypes.ModuleName, tokenomicstypes.ModuleName, sdk.NewCoins(newMintCoin), ); err != nil { return tokenomicstypes.ErrTokenomicsApplicationReimbursementRequestFailed.Wrapf( @@ -550,17 +546,19 @@ func (k Keeper) TokenLogicModuleGlobalMintReimbursementRequest( // Prepare and emit the event for the application being overcharged. reimbursementRequestEvent := &tokenomicstypes.EventApplicationReimbursementRequest{ - ApplicationAddr: application.Address, - ServiceId: service.Id, - SessionId: sessionHeader.SessionId, - Amount: &newMintCoin, + ApplicationAddr: application.Address, + SupplierOperatorAddr: supplier.OperatorAddress, + SupplierOwnerAddr: supplier.OwnerAddress, + ServiceId: service.Id, + SessionId: sessionHeader.SessionId, + Amount: &newMintCoin, } eventManger := cosmostypes.UnwrapSDKContext(ctx).EventManager() if err := eventManger.EmitTypedEvent(reimbursementRequestEvent); err != nil { return tokenomicstypes.ErrTokenomicsEmittingEventFailed.Wrapf( - "error emitting event %v", - reimbursementRequestEvent, + "(%+v): %s", + reimbursementRequestEvent, err, ) } @@ -645,8 +643,8 @@ func (k Keeper) ensureClaimAmountLimits( logger log.Logger, application *apptypes.Application, supplier *sharedtypes.Supplier, - initialApplicationStake cosmostypes.Coin, claimSettlementCoin cosmostypes.Coin, + initialApplicationStake cosmostypes.Coin, ) ( actualSettlementCoins cosmostypes.Coin, err error, @@ -665,10 +663,11 @@ func (k Keeper) ensureClaimAmountLimits( globalInflationCoin, _ := calculateGlobalPerClaimMintInflationFromSettlementAmount(claimSettlementCoin) globalInflationAmt := globalInflationCoin.Amount stakeRequirementAmt := claimSettlementCoin.Amount.Add(globalInflationAmt) + totalClaimedCoin := sdk.NewCoin(volatile.DenomuPOKT, stakeRequirementAmt) // TODO_BETA(@red-0ne): Introduce a session sliding window to account for potential consumption // during the current session (i.e. Not the session being settled) such as: - // maxCalibmableAmt = (AppStake / (currSessNum - settlingSessNum + 1) / NumSuppliersPerSession) + // maxClaimableAmt = (AppStake / (currSessNum - settlingSessNum + 1) / NumSuppliersPerSession) // In conjunction with single service applications, this would make maxClaimableAmt // effectively addressing the issue of over-servicing. // Example: @@ -683,7 +682,7 @@ func (k Keeper) ensureClaimAmountLimits( // the application will consume its maxClaimableAmt the current session (3). // - Off-chain actors could use this formula during the servicing of session num 3 // and assume maxClaimableAmt will be settled in session 2. - // - Garantee no over-servicing at the cost of higher application stake requirements. + // - Guarantee no over-servicing at the cost of higher application stake requirements. maxClaimableAmt := appStake.Amount.Quo(math.NewInt(sessionkeeper.NumSupplierPerSession)) maxClaimSettlementAmt := stakeToMaxSettlementAmount(maxClaimableAmt) @@ -717,13 +716,11 @@ func (k Keeper) ensureClaimAmountLimits( // Determine the max claimable amount for the supplier based on the application's stake in this session. maxClaimableCoin := sdk.NewCoin(volatile.DenomuPOKT, maxClaimSettlementAmt) - stakeRequirementCoin := sdk.NewCoin(volatile.DenomuPOKT, stakeRequirementAmt) - // Prepare and emit the event for the application being overserviced applicationOverservicedEvent := &tokenomicstypes.EventApplicationOverserviced{ ApplicationAddr: application.GetAddress(), SupplierOperatorAddr: supplier.GetOperatorAddress(), - ExpectedBurn: &stakeRequirementCoin, + ExpectedBurn: &totalClaimedCoin, EffectiveBurn: &maxClaimableCoin, } eventManager := cosmostypes.UnwrapSDKContext(ctx).EventManager() diff --git a/x/tokenomics/keeper/token_logic_modules_test.go b/x/tokenomics/keeper/token_logic_modules_test.go index 2991cbfda..51bd4e46a 100644 --- a/x/tokenomics/keeper/token_logic_modules_test.go +++ b/x/tokenomics/keeper/token_logic_modules_test.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "fmt" + math2 "math" "testing" "cosmossdk.io/math" @@ -118,7 +119,7 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMint_Valid(t *testing.T) { claim := prepareTestClaim(numRelays, service, &app, &supplier) // Process the token logic modules - err = keepers.ProcessTokenLogicModules(ctx, &claim) + err = keepers.ProcessTokenLogicModules(ctx, &claim, appStake) require.NoError(t, err) // Assert that `applicationAddress` account balance is *unchanged* @@ -166,7 +167,7 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMint_Valid(t *testing.T) { // DEV_NOTE: Most of the setup here is a copy-paste of TLMBurnEqualsMintValid // except that the application stake is calculated to explicitly be too low to // handle all the relays completed. -func TestProcessTokenLogicModules_TLMBurnEqualsMint_Invalid_SupplierExceedsMaxClaimableAmount(t *testing.T) { +func TestProcessTokenLogicModules_TLMBurnEqualsMint_Valid_SupplierExceedsMaxClaimableAmount(t *testing.T) { // Test Parameters globalComputeUnitsToTokensMultiplier := uint64(1) serviceComputeUnitsPerRelay := uint64(100) @@ -248,7 +249,7 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMint_Invalid_SupplierExceedsMaxCl claim := prepareTestClaim(numRelays, service, &app, &supplier) // Process the token logic modules - err = keepers.ProcessTokenLogicModules(ctx, &claim) + err = keepers.ProcessTokenLogicModules(ctx, &claim, appStake) require.NoError(t, err) // Assert that `applicationAddress` account balance is *unchanged* @@ -383,7 +384,7 @@ func TestProcessTokenLogicModules_TLMGlobalMint_Valid_MintDistributionCorrect(t } // Process the token logic modules - err = keepers.ProcessTokenLogicModules(ctx, &claim) + err = keepers.ProcessTokenLogicModules(ctx, &claim, appStake) require.NoError(t, err) // Determine balances after inflation @@ -451,7 +452,7 @@ func TestProcessTokenLogicModules_AppNotFound(t *testing.T) { } // Process the token logic modules - err := keeper.ProcessTokenLogicModules(ctx, &claim) + err := keeper.ProcessTokenLogicModules(ctx, &claim, uPOKTCoin(math2.MaxInt)) require.Error(t, err) require.ErrorIs(t, err, tokenomicstypes.ErrTokenomicsApplicationNotFound) } @@ -474,7 +475,7 @@ func TestProcessTokenLogicModules_ServiceNotFound(t *testing.T) { } // Execute test function - err := keeper.ProcessTokenLogicModules(ctx, &claim) + err := keeper.ProcessTokenLogicModules(ctx, &claim, uPOKTCoin(math2.MaxInt)) require.Error(t, err) require.ErrorIs(t, err, tokenomicstypes.ErrTokenomicsServiceNotFound) @@ -544,7 +545,7 @@ func TestProcessTokenLogicModules_InvalidRoot(t *testing.T) { claim.RootHash = smt.MerkleRoot(test.root[:]) // Execute test function - err := keeper.ProcessTokenLogicModules(ctx, &claim) + err := keeper.ProcessTokenLogicModules(ctx, &claim, uPOKTCoin(math2.MaxInt)) // Assert the error if test.errExpected { @@ -634,7 +635,7 @@ func TestProcessTokenLogicModules_InvalidClaim(t *testing.T) { err = fmt.Errorf("panic occurred: %v", r) } }() - return keeper.ProcessTokenLogicModules(ctx, test.claim) + return keeper.ProcessTokenLogicModules(ctx, test.claim, uPOKTCoin(math2.MaxInt)) }() // Assert the error diff --git a/x/tokenomics/types/event.pb.go b/x/tokenomics/types/event.pb.go index d852f7921..8570fd911 100644 --- a/x/tokenomics/types/event.pb.go +++ b/x/tokenomics/types/event.pb.go @@ -372,10 +372,12 @@ func (m *EventSupplierSlashed) GetSlashingAmount() *types1.Coin { // EventApplicationReimbursementRequest is emitted when an application requests // a reimbursement type EventApplicationReimbursementRequest struct { - ApplicationAddr string `protobuf:"bytes,1,opt,name=application_addr,json=applicationAddr,proto3" json:"application_addr,omitempty"` - ServiceId string `protobuf:"bytes,2,opt,name=service_id,json=serviceId,proto3" json:"service_id,omitempty"` - SessionId string `protobuf:"bytes,3,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` - Amount *types1.Coin `protobuf:"bytes,4,opt,name=amount,proto3" json:"amount,omitempty"` + ApplicationAddr string `protobuf:"bytes,1,opt,name=application_addr,json=applicationAddr,proto3" json:"application_addr,omitempty"` + SupplierOperatorAddr string `protobuf:"bytes,2,opt,name=supplier_operator_addr,json=supplierOperatorAddr,proto3" json:"supplier_operator_addr,omitempty"` + SupplierOwnerAddr string `protobuf:"bytes,3,opt,name=supplier_owner_addr,json=supplierOwnerAddr,proto3" json:"supplier_owner_addr,omitempty"` + ServiceId string `protobuf:"bytes,4,opt,name=service_id,json=serviceId,proto3" json:"service_id,omitempty"` + SessionId string `protobuf:"bytes,5,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` + Amount *types1.Coin `protobuf:"bytes,6,opt,name=amount,proto3" json:"amount,omitempty"` } func (m *EventApplicationReimbursementRequest) Reset() { *m = EventApplicationReimbursementRequest{} } @@ -414,6 +416,20 @@ func (m *EventApplicationReimbursementRequest) GetApplicationAddr() string { return "" } +func (m *EventApplicationReimbursementRequest) GetSupplierOperatorAddr() string { + if m != nil { + return m.SupplierOperatorAddr + } + return "" +} + +func (m *EventApplicationReimbursementRequest) GetSupplierOwnerAddr() string { + if m != nil { + return m.SupplierOwnerAddr + } + return "" +} + func (m *EventApplicationReimbursementRequest) GetServiceId() string { if m != nil { return m.ServiceId @@ -447,57 +463,59 @@ func init() { func init() { proto.RegisterFile("poktroll/tokenomics/event.proto", fileDescriptor_a78874bbf91a58c7) } var fileDescriptor_a78874bbf91a58c7 = []byte{ - // 799 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x55, 0x4d, 0x6f, 0x1b, 0x45, - 0x18, 0xce, 0xa6, 0x6e, 0x24, 0x0f, 0xb5, 0x6b, 0x2f, 0x49, 0xe5, 0x06, 0xb2, 0x1b, 0x2c, 0x84, - 0x42, 0x45, 0x77, 0x95, 0x16, 0x71, 0x44, 0xd8, 0xae, 0x8b, 0x56, 0x02, 0xdb, 0x1d, 0x13, 0x54, - 0x71, 0x60, 0x59, 0xef, 0xbe, 0x71, 0x87, 0x78, 0x67, 0xb6, 0x33, 0xb3, 0x26, 0x3d, 0xf2, 0x0f, - 0xf8, 0x45, 0x1c, 0x38, 0x71, 0xec, 0xb1, 0x27, 0x0b, 0x39, 0x37, 0x5f, 0x39, 0x70, 0x45, 0x33, - 0xbb, 0xfe, 0x88, 0x53, 0x1c, 0xa1, 0x5c, 0x7b, 0xb1, 0x77, 0xdf, 0xe7, 0x63, 0x3e, 0x9e, 0x77, - 0x76, 0x90, 0x9d, 0xb0, 0x33, 0xc9, 0xd9, 0x68, 0xe4, 0x4a, 0x76, 0x06, 0x94, 0xc5, 0x24, 0x14, - 0x2e, 0x8c, 0x81, 0x4a, 0x27, 0xe1, 0x4c, 0x32, 0xf3, 0xfd, 0x39, 0xc1, 0x59, 0x12, 0xf6, 0xad, - 0x90, 0x89, 0x98, 0x09, 0x77, 0x10, 0x08, 0x70, 0xc7, 0xc7, 0x03, 0x90, 0xc1, 0xb1, 0x1b, 0x32, - 0x42, 0x33, 0xd1, 0xfe, 0xee, 0x90, 0x0d, 0x99, 0x7e, 0x74, 0xd5, 0x53, 0x5e, 0xdd, 0x5f, 0x8c, - 0x95, 0x70, 0xc6, 0x4e, 0x5d, 0xf9, 0x2a, 0x01, 0x91, 0x61, 0xf5, 0x7f, 0x6e, 0xa1, 0x6a, 0x5b, - 0x0d, 0xdb, 0x1a, 0x05, 0x24, 0x6e, 0x9f, 0x27, 0x84, 0x43, 0x64, 0x7e, 0x81, 0x6e, 0x87, 0xea, - 0xbd, 0x66, 0x1c, 0x1a, 0x47, 0xef, 0x3d, 0xda, 0x73, 0x16, 0x93, 0xd1, 0x0e, 0x8e, 0x26, 0x37, - 0x8b, 0xb3, 0x89, 0x9d, 0xf1, 0x70, 0xf6, 0x67, 0x52, 0x54, 0x05, 0x65, 0x11, 0x48, 0xc2, 0xa8, - 0xcf, 0x21, 0x10, 0x8c, 0xd6, 0xb6, 0x0f, 0x8d, 0xa3, 0xf2, 0xa3, 0x07, 0xce, 0x5b, 0x16, 0xe4, - 0x2c, 0x47, 0xd5, 0x12, 0xac, 0x15, 0xcd, 0xbd, 0xd9, 0xc4, 0xbe, 0x6a, 0x84, 0x2b, 0xb0, 0x46, - 0x34, 0x1f, 0x22, 0x44, 0xd3, 0xd8, 0xe7, 0x30, 0x0a, 0x5e, 0x89, 0xda, 0xad, 0x43, 0xe3, 0xa8, - 0xd0, 0x2c, 0xcf, 0x26, 0xf6, 0x4a, 0x15, 0x17, 0x69, 0x1a, 0x63, 0xfd, 0x68, 0x3e, 0x47, 0xf7, - 0x15, 0xa0, 0xe7, 0x0a, 0x91, 0x1f, 0xb2, 0x38, 0x49, 0x25, 0xf8, 0x29, 0x25, 0x52, 0xd4, 0x0a, - 0x5a, 0x7d, 0x30, 0x9b, 0xd8, 0xff, 0x4d, 0xc2, 0xf7, 0x68, 0x1a, 0xb7, 0x32, 0xa4, 0x95, 0x01, - 0x27, 0xaa, 0x6e, 0xfe, 0x88, 0x3e, 0x50, 0x22, 0x10, 0x92, 0xc4, 0x81, 0xbc, 0xe2, 0x7d, 0x5b, - 0x7b, 0xdb, 0xb3, 0x89, 0xbd, 0x89, 0x86, 0x6b, 0x34, 0x8d, 0xdb, 0x73, 0xec, 0x92, 0xff, 0x33, - 0x54, 0x9a, 0x4f, 0x28, 0x55, 0xfb, 0x58, 0xdb, 0xd1, 0xc1, 0xdc, 0x77, 0xb2, 0x86, 0x70, 0x54, - 0x43, 0x38, 0x79, 0x43, 0x38, 0x2d, 0x46, 0x68, 0xb3, 0x3a, 0x9b, 0xd8, 0x97, 0x35, 0xf8, 0x4e, - 0xfe, 0x7a, 0xa2, 0xde, 0xea, 0x7f, 0x5f, 0x4a, 0xbe, 0x0f, 0x52, 0x8e, 0x6e, 0x90, 0xfc, 0xcf, - 0xa8, 0xaa, 0x09, 0x3e, 0x87, 0x97, 0x29, 0xe1, 0x10, 0x03, 0x95, 0x79, 0xf2, 0x9f, 0xac, 0x7b, - 0xf4, 0xd4, 0x2f, 0x5e, 0xf2, 0x56, 0x53, 0xbf, 0x62, 0x82, 0x2b, 0xc9, 0x1a, 0xfd, 0x5d, 0xea, - 0x37, 0x48, 0xfd, 0xd7, 0x6d, 0xf4, 0xa1, 0x4e, 0xbd, 0x91, 0x24, 0x23, 0x12, 0xea, 0xc3, 0xd4, - 0x1d, 0x03, 0x17, 0xc0, 0xc7, 0x24, 0x84, 0xc8, 0xfc, 0x14, 0x55, 0x82, 0x25, 0xe4, 0x07, 0x51, - 0xc4, 0x75, 0x2f, 0x14, 0xf1, 0xdd, 0x95, 0x7a, 0x23, 0x8a, 0xb8, 0xf9, 0x39, 0xba, 0x27, 0x52, - 0x55, 0x03, 0xee, 0xb3, 0x04, 0x78, 0x20, 0x19, 0xcf, 0x04, 0xdb, 0x5a, 0xb0, 0x3b, 0x47, 0xbb, - 0x39, 0xa8, 0x55, 0x5f, 0xa2, 0x12, 0x9c, 0x27, 0x10, 0xaa, 0x8d, 0x18, 0xa4, 0x9c, 0xea, 0x00, - 0x37, 0x2d, 0x0a, 0xdf, 0x99, 0xf3, 0x9b, 0x29, 0xa7, 0xe6, 0x57, 0xa8, 0x0c, 0xa7, 0xa7, 0x10, - 0x4a, 0x32, 0x86, 0xcc, 0xa0, 0x70, 0x9d, 0x41, 0x69, 0x21, 0x50, 0x0e, 0xf5, 0xdf, 0x0d, 0xb4, - 0xab, 0xf7, 0xa0, 0x9f, 0xcf, 0xaf, 0x3f, 0x0a, 0xc4, 0x0b, 0x88, 0x36, 0x2c, 0xc8, 0xd8, 0xb0, - 0xa0, 0xcf, 0x90, 0xa9, 0xe3, 0xcd, 0xbe, 0x9d, 0x59, 0x0b, 0x09, 0xbd, 0x05, 0x05, 0x5c, 0x51, - 0xd9, 0x66, 0x80, 0x6e, 0x20, 0x61, 0x36, 0xd1, 0x5d, 0xa1, 0x86, 0x23, 0x74, 0xe8, 0x07, 0x31, - 0x4b, 0xa9, 0xbc, 0x7e, 0x03, 0xca, 0x73, 0x45, 0x43, 0x0b, 0xea, 0x7f, 0x18, 0xe8, 0xe3, 0xf5, - 0x10, 0x31, 0x90, 0x78, 0x90, 0x72, 0x91, 0x9f, 0xa8, 0x97, 0x29, 0x08, 0xf9, 0x7f, 0xc2, 0x3c, - 0x40, 0x28, 0xef, 0x01, 0x9f, 0x44, 0x79, 0x80, 0xc5, 0xbc, 0xe2, 0x45, 0x19, 0x2c, 0x84, 0x72, - 0x21, 0x91, 0x9e, 0xb1, 0x86, 0x75, 0xc5, 0x8b, 0xcc, 0x63, 0xb4, 0x93, 0x2f, 0xe6, 0xda, 0x30, - 0x72, 0xe2, 0x83, 0x9f, 0xd0, 0xde, 0x5b, 0xbf, 0xfe, 0xe6, 0x47, 0xe8, 0xa0, 0xfd, 0xbc, 0xe7, - 0xe1, 0xc6, 0x77, 0x5e, 0xb7, 0xe3, 0xe3, 0x76, 0xa3, 0xdf, 0xed, 0xf8, 0x27, 0x9d, 0x7e, 0xaf, - 0xdd, 0xf2, 0x9e, 0x7a, 0xed, 0x27, 0x95, 0x2d, 0xb3, 0x8a, 0x4a, 0x3d, 0xdc, 0xed, 0x3e, 0xf5, - 0xbf, 0xf5, 0xfa, 0x7d, 0xaf, 0xf3, 0x75, 0xc5, 0x58, 0x96, 0xbc, 0xce, 0xf7, 0x8d, 0x6f, 0xbc, - 0x27, 0x95, 0xed, 0xe6, 0xb3, 0x3f, 0xa7, 0x96, 0xf1, 0x7a, 0x6a, 0x19, 0x6f, 0xa6, 0x96, 0xf1, - 0xd7, 0xd4, 0x32, 0x7e, 0xbb, 0xb0, 0xb6, 0x5e, 0x5f, 0x58, 0x5b, 0x6f, 0x2e, 0xac, 0xad, 0x1f, - 0x1e, 0x0f, 0x89, 0x7c, 0x91, 0x0e, 0x9c, 0x90, 0xc5, 0xae, 0x3a, 0x1a, 0x0f, 0x29, 0xc8, 0x5f, - 0x18, 0x3f, 0x73, 0x17, 0xb7, 0xe5, 0xf9, 0xea, 0xdd, 0xac, 0x2f, 0xcd, 0xc1, 0x8e, 0xbe, 0x35, - 0x1f, 0xff, 0x1b, 0x00, 0x00, 0xff, 0xff, 0x5f, 0xc3, 0xae, 0x29, 0xbf, 0x07, 0x00, 0x00, + // 823 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x56, 0xcf, 0x6f, 0xdb, 0x36, + 0x14, 0x8e, 0x9c, 0x34, 0x80, 0xb9, 0xc6, 0xb5, 0xd5, 0xa4, 0x70, 0xb3, 0x45, 0xca, 0x8c, 0x61, + 0xc8, 0x8a, 0x55, 0x42, 0xda, 0x61, 0xc7, 0x61, 0xb6, 0xeb, 0x0e, 0x02, 0x36, 0xdb, 0xa5, 0x97, + 0xa1, 0xd8, 0x61, 0x9a, 0x2c, 0xbd, 0xb8, 0x5c, 0x2c, 0x52, 0x25, 0x29, 0x37, 0x3d, 0xee, 0x3f, + 0xd8, 0x9f, 0xb1, 0xbf, 0x62, 0xe7, 0x1d, 0x7b, 0xec, 0xc9, 0x18, 0x9c, 0x9b, 0xaf, 0x3b, 0xec, + 0x3a, 0x90, 0x92, 0x7f, 0xc4, 0xe9, 0x9c, 0x43, 0xb0, 0x5b, 0x2f, 0x36, 0xf9, 0xbe, 0xef, 0x7b, + 0x24, 0xdf, 0xf7, 0x68, 0x1a, 0xd9, 0x09, 0x3b, 0x93, 0x9c, 0x0d, 0x87, 0xae, 0x64, 0x67, 0x40, + 0x59, 0x4c, 0x42, 0xe1, 0xc2, 0x08, 0xa8, 0x74, 0x12, 0xce, 0x24, 0x33, 0xef, 0xce, 0x08, 0xce, + 0x82, 0xb0, 0x6f, 0x85, 0x4c, 0xc4, 0x4c, 0xb8, 0xfd, 0x40, 0x80, 0x3b, 0x3a, 0xee, 0x83, 0x0c, + 0x8e, 0xdd, 0x90, 0x11, 0x9a, 0x89, 0xf6, 0x77, 0x07, 0x6c, 0xc0, 0xf4, 0xd0, 0x55, 0xa3, 0x3c, + 0xba, 0x3f, 0x5f, 0x2b, 0xe1, 0x8c, 0x9d, 0xba, 0xf2, 0x75, 0x02, 0x22, 0xc3, 0x6a, 0xff, 0x6c, + 0xa2, 0x4a, 0x4b, 0x2d, 0xdb, 0x1c, 0x06, 0x24, 0x6e, 0x9d, 0x27, 0x84, 0x43, 0x64, 0x7e, 0x89, + 0x6e, 0x85, 0x6a, 0x5e, 0x35, 0x0e, 0x8d, 0xa3, 0x0f, 0x1e, 0xed, 0x39, 0xf3, 0xcd, 0xe8, 0x0c, + 0x8e, 0x26, 0x37, 0x8a, 0xd3, 0xb1, 0x9d, 0xf1, 0x70, 0xf6, 0x65, 0x52, 0x54, 0x01, 0x95, 0x22, + 0x90, 0x84, 0x51, 0x9f, 0x43, 0x20, 0x18, 0xad, 0x16, 0x0e, 0x8d, 0xa3, 0xd2, 0xa3, 0x07, 0xce, + 0x3b, 0x0e, 0xe4, 0x2c, 0x56, 0xd5, 0x12, 0xac, 0x15, 0x8d, 0xbd, 0xe9, 0xd8, 0xbe, 0x9a, 0x08, + 0x97, 0x61, 0x85, 0x68, 0x3e, 0x44, 0x88, 0xa6, 0xb1, 0xcf, 0x61, 0x18, 0xbc, 0x16, 0xd5, 0xcd, + 0x43, 0xe3, 0x68, 0xab, 0x51, 0x9a, 0x8e, 0xed, 0xa5, 0x28, 0x2e, 0xd2, 0x34, 0xc6, 0x7a, 0x68, + 0x3e, 0x47, 0xf7, 0x15, 0xa0, 0xf7, 0x0a, 0x91, 0x1f, 0xb2, 0x38, 0x49, 0x25, 0xf8, 0x29, 0x25, + 0x52, 0x54, 0xb7, 0xb4, 0xfa, 0x60, 0x3a, 0xb6, 0xff, 0x9b, 0x84, 0xef, 0xd1, 0x34, 0x6e, 0x66, + 0x48, 0x33, 0x03, 0x4e, 0x54, 0xdc, 0xfc, 0x09, 0x7d, 0xa8, 0x44, 0x20, 0x24, 0x89, 0x03, 0x79, + 0x25, 0xf7, 0x2d, 0x9d, 0xdb, 0x9e, 0x8e, 0xed, 0x75, 0x34, 0x5c, 0xa5, 0x69, 0xdc, 0x9a, 0x61, + 0x97, 0xf2, 0x3f, 0x43, 0x3b, 0xb3, 0x0d, 0xa5, 0xaa, 0x8e, 0xd5, 0x6d, 0x6d, 0xcc, 0x7d, 0x27, + 0x6b, 0x08, 0x47, 0x35, 0x84, 0x93, 0x37, 0x84, 0xd3, 0x64, 0x84, 0x36, 0x2a, 0xd3, 0xb1, 0x7d, + 0x59, 0x83, 0x6f, 0xe7, 0xd3, 0x13, 0x35, 0xab, 0xfd, 0x7d, 0xc9, 0xf9, 0x1e, 0x48, 0x39, 0xbc, + 0x81, 0xf3, 0xbf, 0xa0, 0x8a, 0x26, 0xf8, 0x1c, 0x5e, 0xa6, 0x84, 0x43, 0x0c, 0x54, 0xe6, 0xce, + 0x7f, 0xba, 0x9a, 0xa3, 0xab, 0x3e, 0xf1, 0x82, 0xb7, 0xec, 0xfa, 0x95, 0x24, 0xb8, 0x9c, 0xac, + 0xd0, 0xdf, 0xbb, 0x7e, 0x03, 0xd7, 0x7f, 0x2d, 0xa0, 0x8f, 0xb4, 0xeb, 0xf5, 0x24, 0x19, 0x92, + 0x50, 0x5f, 0xa6, 0xce, 0x08, 0xb8, 0x00, 0x3e, 0x22, 0x21, 0x44, 0xe6, 0x67, 0xa8, 0x1c, 0x2c, + 0x20, 0x3f, 0x88, 0x22, 0xae, 0x7b, 0xa1, 0x88, 0xef, 0x2c, 0xc5, 0xeb, 0x51, 0xc4, 0xcd, 0x2f, + 0xd0, 0x3d, 0x91, 0xaa, 0x18, 0x70, 0x9f, 0x25, 0xc0, 0x03, 0xc9, 0x78, 0x26, 0x28, 0x68, 0xc1, + 0xee, 0x0c, 0xed, 0xe4, 0xa0, 0x56, 0x7d, 0x85, 0x76, 0xe0, 0x3c, 0x81, 0x50, 0x15, 0xa2, 0x9f, + 0x72, 0xaa, 0x0d, 0x5c, 0x77, 0x28, 0x7c, 0x7b, 0xc6, 0x6f, 0xa4, 0x9c, 0x9a, 0x5f, 0xa3, 0x12, + 0x9c, 0x9e, 0x42, 0x28, 0xc9, 0x08, 0xb2, 0x04, 0x5b, 0xd7, 0x25, 0xd8, 0x99, 0x0b, 0x54, 0x86, + 0xda, 0x1f, 0x06, 0xda, 0xd5, 0x35, 0xe8, 0xe5, 0xfb, 0xeb, 0x0d, 0x03, 0xf1, 0x02, 0xa2, 0x35, + 0x07, 0x32, 0xd6, 0x1c, 0xe8, 0x73, 0x64, 0x6a, 0x7b, 0xb3, 0xdf, 0xce, 0xac, 0x85, 0x84, 0x2e, + 0xc1, 0x16, 0x2e, 0x2b, 0x6f, 0x33, 0x40, 0x37, 0x90, 0x30, 0x1b, 0xe8, 0x8e, 0x50, 0xcb, 0x11, + 0x3a, 0xf0, 0x83, 0x98, 0xa5, 0x54, 0x5e, 0x5f, 0x80, 0xd2, 0x4c, 0x51, 0xd7, 0x82, 0xda, 0xef, + 0x05, 0xf4, 0xc9, 0xaa, 0x89, 0x18, 0x48, 0xdc, 0x4f, 0xb9, 0xc8, 0x6f, 0xd4, 0xcb, 0x14, 0x84, + 0xfc, 0xff, 0xcd, 0x74, 0xd0, 0xdd, 0x85, 0xea, 0x15, 0x85, 0x5c, 0xb2, 0xa9, 0x25, 0x95, 0xb9, + 0x44, 0x21, 0x9a, 0x7f, 0x80, 0x50, 0xde, 0x69, 0x3e, 0x89, 0xb4, 0x71, 0x45, 0x5c, 0xcc, 0x23, + 0x5e, 0x94, 0xc1, 0x42, 0xa8, 0xbd, 0x92, 0x48, 0xdf, 0x1f, 0x0d, 0xeb, 0x88, 0x17, 0x99, 0xc7, + 0x68, 0x3b, 0x2f, 0xd9, 0x75, 0x17, 0x01, 0xe7, 0xc4, 0x07, 0x3f, 0xa3, 0xbd, 0x77, 0xbe, 0x31, + 0xe6, 0xc7, 0xe8, 0xa0, 0xf5, 0xbc, 0xeb, 0xe1, 0xfa, 0xf7, 0x5e, 0xa7, 0xed, 0xe3, 0x56, 0xbd, + 0xd7, 0x69, 0xfb, 0x27, 0xed, 0x5e, 0xb7, 0xd5, 0xf4, 0x9e, 0x7a, 0xad, 0x27, 0xe5, 0x0d, 0xb3, + 0x82, 0x76, 0xba, 0xb8, 0xd3, 0x79, 0xea, 0x7f, 0xe7, 0xf5, 0x7a, 0x5e, 0xfb, 0x9b, 0xb2, 0xb1, + 0x08, 0x79, 0xed, 0x1f, 0xea, 0xdf, 0x7a, 0x4f, 0xca, 0x85, 0xc6, 0xb3, 0x3f, 0x27, 0x96, 0xf1, + 0x66, 0x62, 0x19, 0x6f, 0x27, 0x96, 0xf1, 0xd7, 0xc4, 0x32, 0x7e, 0xbb, 0xb0, 0x36, 0xde, 0x5c, + 0x58, 0x1b, 0x6f, 0x2f, 0xac, 0x8d, 0x1f, 0x1f, 0x0f, 0x88, 0x7c, 0x91, 0xf6, 0x9d, 0x90, 0xc5, + 0xae, 0xba, 0x80, 0x0f, 0x29, 0xc8, 0x57, 0x8c, 0x9f, 0xb9, 0xf3, 0x37, 0xf9, 0x7c, 0xf9, 0x1f, + 0x80, 0x7e, 0x9a, 0xfb, 0xdb, 0xfa, 0x6d, 0x7e, 0xfc, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x8b, + 0xd5, 0xac, 0x44, 0x25, 0x08, 0x00, 0x00, } func (m *EventClaimExpired) Marshal() (dAtA []byte, err error) { @@ -772,20 +790,34 @@ func (m *EventApplicationReimbursementRequest) MarshalToSizedBuffer(dAtA []byte) i = encodeVarintEvent(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x22 + dAtA[i] = 0x32 } if len(m.SessionId) > 0 { i -= len(m.SessionId) copy(dAtA[i:], m.SessionId) i = encodeVarintEvent(dAtA, i, uint64(len(m.SessionId))) i-- - dAtA[i] = 0x1a + dAtA[i] = 0x2a } if len(m.ServiceId) > 0 { i -= len(m.ServiceId) copy(dAtA[i:], m.ServiceId) i = encodeVarintEvent(dAtA, i, uint64(len(m.ServiceId))) i-- + dAtA[i] = 0x22 + } + if len(m.SupplierOwnerAddr) > 0 { + i -= len(m.SupplierOwnerAddr) + copy(dAtA[i:], m.SupplierOwnerAddr) + i = encodeVarintEvent(dAtA, i, uint64(len(m.SupplierOwnerAddr))) + i-- + dAtA[i] = 0x1a + } + if len(m.SupplierOperatorAddr) > 0 { + i -= len(m.SupplierOperatorAddr) + copy(dAtA[i:], m.SupplierOperatorAddr) + i = encodeVarintEvent(dAtA, i, uint64(len(m.SupplierOperatorAddr))) + i-- dAtA[i] = 0x12 } if len(m.ApplicationAddr) > 0 { @@ -922,6 +954,14 @@ func (m *EventApplicationReimbursementRequest) Size() (n int) { if l > 0 { n += 1 + l + sovEvent(uint64(l)) } + l = len(m.SupplierOperatorAddr) + if l > 0 { + n += 1 + l + sovEvent(uint64(l)) + } + l = len(m.SupplierOwnerAddr) + if l > 0 { + n += 1 + l + sovEvent(uint64(l)) + } l = len(m.ServiceId) if l > 0 { n += 1 + l + sovEvent(uint64(l)) @@ -1724,6 +1764,70 @@ func (m *EventApplicationReimbursementRequest) Unmarshal(dAtA []byte) error { m.ApplicationAddr = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SupplierOperatorAddr", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + 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 ErrInvalidLengthEvent + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvent + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SupplierOperatorAddr = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SupplierOwnerAddr", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + 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 ErrInvalidLengthEvent + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvent + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SupplierOwnerAddr = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field ServiceId", wireType) } @@ -1755,7 +1859,7 @@ func (m *EventApplicationReimbursementRequest) Unmarshal(dAtA []byte) error { } m.ServiceId = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 3: + case 5: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field SessionId", wireType) } @@ -1787,7 +1891,7 @@ func (m *EventApplicationReimbursementRequest) Unmarshal(dAtA []byte) error { } m.SessionId = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 4: + case 6: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) } From fafd2f3be3eef85fa42a87a39afbd0ca69885c4b Mon Sep 17 00:00:00 2001 From: Redouane Lakrache Date: Fri, 25 Oct 2024 00:03:21 +0200 Subject: [PATCH 24/31] chore: Address reveiw change requests --- testutil/keeper/tokenomics.go | 4 ++-- x/tokenomics/keeper/token_logic_modules.go | 13 +++++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/testutil/keeper/tokenomics.go b/testutil/keeper/tokenomics.go index 79d3cb828..4fee376fd 100644 --- a/testutil/keeper/tokenomics.go +++ b/testutil/keeper/tokenomics.go @@ -515,11 +515,11 @@ func WithProposerAddr(addr string) TokenomicsModuleKeepersOpt { } // WithProofRequirement is an option to set the proof requirement in the tokenomics module keepers. -func WithProofRequirement(required bool) TokenomicsModuleKeepersOpt { +func WithProofRequirement(proofRequired bool) TokenomicsModuleKeepersOpt { return func(ctx context.Context, keepers *TokenomicsModuleKeepers) context.Context { proofParams := keepers.ProofKeeper.GetParams(ctx) - if required { + if proofRequired { proofParams.ProofRequestProbability = 1 proofRequirementThreshold := cosmostypes.NewInt64Coin(volatile.DenomuPOKT, 0) proofParams.ProofRequirementThreshold = &proofRequirementThreshold diff --git a/x/tokenomics/keeper/token_logic_modules.go b/x/tokenomics/keeper/token_logic_modules.go index 1d9ae4446..d998cdba5 100644 --- a/x/tokenomics/keeper/token_logic_modules.go +++ b/x/tokenomics/keeper/token_logic_modules.go @@ -125,8 +125,11 @@ func init() { panic("mint allocation percentages do not add to 1.0") } - // TODO_UPNEXT(@Olshansk): Ensure that if `TLMGlobalMint` is present in the map, - // then TLMGlobalMintReimbursementRequest will need to be there too. + _, hasGlobalMintTLM := tokenLogicModuleProcessorMap[TLMGlobalMint] + _, hasGlobalMintReimbursementRequestTLM := tokenLogicModuleProcessorMap[TLMGlobalMintReimbursementRequest] + if hasGlobalMintTLM != hasGlobalMintReimbursementRequestTLM { + panic("TLMGlobalMint and TLMGlobalMintReimbursementRequest must be activated together") + } } // ProcessTokenLogicModules is the entrypoint for all TLM processing. @@ -518,12 +521,12 @@ func (k Keeper) TokenLogicModuleGlobalMintReimbursementRequest( ); err != nil { return tokenomicstypes.ErrTokenomicsApplicationReimbursementRequestFailed.Wrapf( "sending %s from the application module account to the tokenomics module account: %v", - actualSettlementCoin, err, + newMintCoin, err, ) } logger.Info(fmt.Sprintf( "sent (%s) from the application module account to the tokenomics module account", - actualSettlementCoin, + newMintCoin, )) // Send the global per claim mint inflation uPOKT from the tokenomics module @@ -638,6 +641,8 @@ func (k Keeper) sendRewardsToAccount( // If this is not the case, then the supplier essentially did "free work" and the // actual claim amount is less than what was claimed. // Ref: https://arxiv.org/pdf/2305.10672 +// TODO_TEST: Add more tests for edge cases that exercise all the code paths +// actualSettlementCoins could be updated in this function. func (k Keeper) ensureClaimAmountLimits( ctx context.Context, logger log.Logger, From 3185741f43a691170ece3fad018ab7600ad9c0f2 Mon Sep 17 00:00:00 2001 From: Redouane Lakrache Date: Fri, 25 Oct 2024 13:19:30 +0200 Subject: [PATCH 25/31] fix: Add globalmint to tests --- .../integration/application/min_stake_test.go | 20 +++++++++++++++++-- x/tokenomics/keeper/settle_pending_claims.go | 1 + 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/tests/integration/application/min_stake_test.go b/tests/integration/application/min_stake_test.go index fd6eae501..43c801a33 100644 --- a/tests/integration/application/min_stake_test.go +++ b/tests/integration/application/min_stake_test.go @@ -2,6 +2,7 @@ package application import ( "context" + "math/big" "testing" cosmoslog "cosmossdk.io/log" @@ -25,6 +26,7 @@ import ( sessiontypes "github.com/pokt-network/poktroll/x/session/types" sharedtypes "github.com/pokt-network/poktroll/x/shared/types" suppliertypes "github.com/pokt-network/poktroll/x/supplier/types" + tokenomicskeeper "github.com/pokt-network/poktroll/x/tokenomics/keeper" ) type applicationMinStakeTestSuite struct { @@ -235,7 +237,8 @@ func (s *applicationMinStakeTestSuite) getExpectedApp(claim *prooftypes.Claim) * expectedBurnCoin, err := claim.GetClaimeduPOKT(sharedParams, relayMiningDifficulty) require.NoError(s.T(), err) - expectedEndStake := s.appStake.Sub(expectedBurnCoin) + globalInflationAmt := calculateGlobalInflation(expectedBurnCoin.Amount) + expectedEndStake := s.appStake.Sub(expectedBurnCoin).SubAmount(globalInflationAmt) return &apptypes.Application{ Address: s.appBech32, Stake: &expectedEndStake, @@ -305,7 +308,20 @@ func (s *applicationMinStakeTestSuite) assertAppStakeIsReturnedToBalance() { s.T().Helper() expectedAppBurn := math.NewInt(int64(s.numRelays * s.numComputeUnitsPerRelay * sharedtypes.DefaultComputeUnitsToTokensMultiplier)) - expectedAppBalance := s.appStake.SubAmount(expectedAppBurn) + globalInflationAmt := calculateGlobalInflation(expectedAppBurn) + expectedAppBalance := s.appStake.SubAmount(expectedAppBurn).SubAmount(globalInflationAmt) + appBalance := s.getAppBalance() require.Equal(s.T(), expectedAppBalance.Amount.Int64(), appBalance.Amount.Int64()) } + +// calculateGlobalInflation calculates the global inflation for the given settlement amount. +func calculateGlobalInflation(settlementAmt math.Int) math.Int { + globalInflationFloat := new(big.Float).Mul( + new(big.Float).SetInt(settlementAmt.BigInt()), + big.NewFloat(tokenomicskeeper.MintPerClaimedTokenGlobalInflation), + ) + globalInflationInt, _ := globalInflationFloat.Int(nil) + + return math.NewIntFromBigInt(globalInflationInt) +} diff --git a/x/tokenomics/keeper/settle_pending_claims.go b/x/tokenomics/keeper/settle_pending_claims.go index c70773ff5..b6c284b30 100644 --- a/x/tokenomics/keeper/settle_pending_claims.go +++ b/x/tokenomics/keeper/settle_pending_claims.go @@ -8,6 +8,7 @@ import ( "github.com/cosmos/cosmos-sdk/types/query" "github.com/pokt-network/poktroll/app/volatile" + apptypes "github.com/pokt-network/poktroll/x/application/types" prooftypes "github.com/pokt-network/poktroll/x/proof/types" servicekeeper "github.com/pokt-network/poktroll/x/service/keeper" sharedtypes "github.com/pokt-network/poktroll/x/shared/types" From 1593bfbd3a5a50a40f14053361d8e8ea964bf5e0 Mon Sep 17 00:00:00 2001 From: Redouane Lakrache Date: Fri, 25 Oct 2024 13:32:25 +0200 Subject: [PATCH 26/31] fix: Linting errors --- x/tokenomics/keeper/settle_pending_claims.go | 2 +- x/tokenomics/keeper/token_logic_modules.go | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/x/tokenomics/keeper/settle_pending_claims.go b/x/tokenomics/keeper/settle_pending_claims.go index b6c284b30..09a9fc26b 100644 --- a/x/tokenomics/keeper/settle_pending_claims.go +++ b/x/tokenomics/keeper/settle_pending_claims.go @@ -42,7 +42,7 @@ func (k Keeper) SettlePendingClaims(ctx sdk.Context) ( for _, claim := range expiringClaims { app, isAppFound := k.applicationKeeper.GetApplication(ctx, claim.SessionHeader.ApplicationAddress) if !isAppFound { - err := apptypes.ErrAppNotFound.Wrapf("application address: %q", claim.SessionHeader.ApplicationAddress) + err = apptypes.ErrAppNotFound.Wrapf("application address: %q", claim.SessionHeader.ApplicationAddress) return settledResult, expiredResult, err } diff --git a/x/tokenomics/keeper/token_logic_modules.go b/x/tokenomics/keeper/token_logic_modules.go index 0936064bf..657a2b5a7 100644 --- a/x/tokenomics/keeper/token_logic_modules.go +++ b/x/tokenomics/keeper/token_logic_modules.go @@ -712,7 +712,6 @@ func (k Keeper) ensureClaimAmountLimits( stakeRequirementAmt = maxClaimableAmt maxClaimSettlementAmt = stakeToMaxSettlementAmount(stakeRequirementAmt) - globalInflationAmt = stakeRequirementAmt.Sub(maxClaimSettlementAmt) } // Check if the claimable amount should be capped by an insufficient application stake. @@ -721,7 +720,6 @@ func (k Keeper) ensureClaimAmountLimits( supplier.GetOperatorAddress(), application.GetAddress(), claimSettlementCoin, maxClaimableAmt)) stakeRequirementAmt = maxClaimableAmt maxClaimSettlementAmt = stakeToMaxSettlementAmount(stakeRequirementAmt) - globalInflationAmt = stakeRequirementAmt.Sub(maxClaimSettlementAmt) } // Nominal case: The claimable amount is within the limits set by Relay Mining. From b2a14b2e81e33813dcf60bd816dc531df139eee9 Mon Sep 17 00:00:00 2001 From: Redouane Lakrache Date: Fri, 25 Oct 2024 15:17:43 +0200 Subject: [PATCH 27/31] fix: Check cached stake before query --- x/tokenomics/keeper/settle_pending_claims.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/x/tokenomics/keeper/settle_pending_claims.go b/x/tokenomics/keeper/settle_pending_claims.go index 09a9fc26b..ca8d5d533 100644 --- a/x/tokenomics/keeper/settle_pending_claims.go +++ b/x/tokenomics/keeper/settle_pending_claims.go @@ -40,13 +40,18 @@ func (k Keeper) SettlePendingClaims(ctx sdk.Context) ( // max share any claim could receive from the application stake. applicationInitialStakeMap := make(map[string]sdk.Coin) for _, claim := range expiringClaims { - app, isAppFound := k.applicationKeeper.GetApplication(ctx, claim.SessionHeader.ApplicationAddress) + appAddress := claim.SessionHeader.ApplicationAddress + if _, isAppFound := applicationInitialStakeMap[appAddress]; isAppFound { + continue + } + + app, isAppFound := k.applicationKeeper.GetApplication(ctx, appAddress) if !isAppFound { - err = apptypes.ErrAppNotFound.Wrapf("application address: %q", claim.SessionHeader.ApplicationAddress) + err = apptypes.ErrAppNotFound.Wrapf("application address: %q", appAddress) return settledResult, expiredResult, err } - applicationInitialStakeMap[claim.SessionHeader.ApplicationAddress] = *app.GetStake() + applicationInitialStakeMap[appAddress] = *app.GetStake() } blockHeight := ctx.BlockHeight() From 5e6e514b3ef020b62780dbacaa2f30a651427d79 Mon Sep 17 00:00:00 2001 From: Redouane Lakrache Date: Fri, 25 Oct 2024 15:35:05 +0200 Subject: [PATCH 28/31] fix: Remove redundant check --- x/tokenomics/keeper/settle_pending_claims.go | 2 ++ x/tokenomics/keeper/token_logic_modules.go | 8 -------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/x/tokenomics/keeper/settle_pending_claims.go b/x/tokenomics/keeper/settle_pending_claims.go index ca8d5d533..91b1afdba 100644 --- a/x/tokenomics/keeper/settle_pending_claims.go +++ b/x/tokenomics/keeper/settle_pending_claims.go @@ -38,6 +38,8 @@ func (k Keeper) SettlePendingClaims(ctx sdk.Context) ( // Capture the applications initial stake which will be used to calculate the // max share any claim could receive from the application stake. + // This ensures that each claim can calculate the maximum amount it can take + // from an application's stake. applicationInitialStakeMap := make(map[string]sdk.Coin) for _, claim := range expiringClaims { appAddress := claim.SessionHeader.ApplicationAddress diff --git a/x/tokenomics/keeper/token_logic_modules.go b/x/tokenomics/keeper/token_logic_modules.go index 657a2b5a7..0dac283f6 100644 --- a/x/tokenomics/keeper/token_logic_modules.go +++ b/x/tokenomics/keeper/token_logic_modules.go @@ -714,14 +714,6 @@ func (k Keeper) ensureClaimAmountLimits( maxClaimSettlementAmt = stakeToMaxSettlementAmount(stakeRequirementAmt) } - // Check if the claimable amount should be capped by an insufficient application stake. - if maxClaimableAmt.LT(stakeRequirementAmt) { - logger.Warn(fmt.Sprintf("Claim by supplier %q EXCEEDS application %q claimable stake. Claim amount > App claimable stake: %v > %v", - supplier.GetOperatorAddress(), application.GetAddress(), claimSettlementCoin, maxClaimableAmt)) - stakeRequirementAmt = maxClaimableAmt - maxClaimSettlementAmt = stakeToMaxSettlementAmount(stakeRequirementAmt) - } - // Nominal case: The claimable amount is within the limits set by Relay Mining. if claimSettlementCoin.Amount.LTE(maxClaimSettlementAmt) { logger.Info(fmt.Sprintf("Claim by supplier %s IS WITHIN LIMITS of servicing application %s. Max claimable amount >= Claim amount: %v >= %v", From 7bd60586ba3a41ada906662c50453e36b5abd048 Mon Sep 17 00:00:00 2001 From: Redouane Lakrache Date: Tue, 29 Oct 2024 01:22:29 +0100 Subject: [PATCH 29/31] chore: Address review change requests --- proto/poktroll/tokenomics/event.proto | 2 +- .../integration/application/min_stake_test.go | 24 ++--- testutil/keeper/tokenomics.go | 19 ++-- x/tokenomics/keeper/settle_pending_claims.go | 57 +++++++---- x/tokenomics/keeper/token_logic_modules.go | 99 +++++++++++-------- .../keeper/token_logic_modules_test.go | 70 +++++++------ 6 files changed, 158 insertions(+), 113 deletions(-) diff --git a/proto/poktroll/tokenomics/event.proto b/proto/poktroll/tokenomics/event.proto index c3751c60d..23c4f8e10 100644 --- a/proto/poktroll/tokenomics/event.proto +++ b/proto/poktroll/tokenomics/event.proto @@ -82,7 +82,7 @@ message EventSupplierSlashed { } // EventApplicationReimbursementRequest is emitted when an application requests -// a reimbursement +// a reimbursement. message EventApplicationReimbursementRequest { string application_addr = 1; string supplier_operator_addr = 2; diff --git a/tests/integration/application/min_stake_test.go b/tests/integration/application/min_stake_test.go index 43c801a33..52bc57912 100644 --- a/tests/integration/application/min_stake_test.go +++ b/tests/integration/application/min_stake_test.go @@ -2,11 +2,9 @@ package application import ( "context" - "math/big" "testing" cosmoslog "cosmossdk.io/log" - "cosmossdk.io/math" cosmostypes "github.com/cosmos/cosmos-sdk/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/stretchr/testify/require" @@ -237,8 +235,8 @@ func (s *applicationMinStakeTestSuite) getExpectedApp(claim *prooftypes.Claim) * expectedBurnCoin, err := claim.GetClaimeduPOKT(sharedParams, relayMiningDifficulty) require.NoError(s.T(), err) - globalInflationAmt := calculateGlobalInflation(expectedBurnCoin.Amount) - expectedEndStake := s.appStake.Sub(expectedBurnCoin).SubAmount(globalInflationAmt) + globalInflationAmt, _ := tokenomicskeeper.CalculateGlobalPerClaimMintInflationFromSettlementAmount(expectedBurnCoin) + expectedEndStake := s.appStake.Sub(expectedBurnCoin).Sub(globalInflationAmt) return &apptypes.Application{ Address: s.appBech32, Stake: &expectedEndStake, @@ -307,21 +305,11 @@ func (s *applicationMinStakeTestSuite) assertUnbondingEndEventObserved(expectedA func (s *applicationMinStakeTestSuite) assertAppStakeIsReturnedToBalance() { s.T().Helper() - expectedAppBurn := math.NewInt(int64(s.numRelays * s.numComputeUnitsPerRelay * sharedtypes.DefaultComputeUnitsToTokensMultiplier)) - globalInflationAmt := calculateGlobalInflation(expectedAppBurn) - expectedAppBalance := s.appStake.SubAmount(expectedAppBurn).SubAmount(globalInflationAmt) + expectedAppBurn := int64(s.numRelays * s.numComputeUnitsPerRelay * sharedtypes.DefaultComputeUnitsToTokensMultiplier) + expectedAppBurnCoin := cosmostypes.NewInt64Coin(volatile.DenomuPOKT, expectedAppBurn) + globalInflationCoin, _ := tokenomicskeeper.CalculateGlobalPerClaimMintInflationFromSettlementAmount(expectedAppBurnCoin) + expectedAppBalance := s.appStake.Sub(expectedAppBurnCoin).Sub(globalInflationCoin) appBalance := s.getAppBalance() require.Equal(s.T(), expectedAppBalance.Amount.Int64(), appBalance.Amount.Int64()) } - -// calculateGlobalInflation calculates the global inflation for the given settlement amount. -func calculateGlobalInflation(settlementAmt math.Int) math.Int { - globalInflationFloat := new(big.Float).Mul( - new(big.Float).SetInt(settlementAmt.BigInt()), - big.NewFloat(tokenomicskeeper.MintPerClaimedTokenGlobalInflation), - ) - globalInflationInt, _ := globalInflationFloat.Int(nil) - - return math.NewIntFromBigInt(globalInflationInt) -} diff --git a/testutil/keeper/tokenomics.go b/testutil/keeper/tokenomics.go index e170117ab..73d6f8a05 100644 --- a/testutil/keeper/tokenomics.go +++ b/testutil/keeper/tokenomics.go @@ -6,7 +6,7 @@ import ( "testing" "cosmossdk.io/log" - sdkmath "cosmossdk.io/math" + cosmosmath "cosmossdk.io/math" "cosmossdk.io/store" "cosmossdk.io/store/metrics" storetypes "cosmossdk.io/store/types" @@ -119,7 +119,7 @@ func TokenomicsKeeperWithActorAddrs(t testing.TB) ( // Prepare the test application. application := apptypes.Application{ Address: sample.AccAddress(), - Stake: &sdk.Coin{Denom: "upokt", Amount: sdkmath.NewInt(100000)}, + Stake: &sdk.Coin{Denom: "upokt", Amount: cosmosmath.NewInt(100000)}, ServiceConfigs: []*sharedtypes.ApplicationServiceConfig{{ServiceId: service.Id}}, } @@ -128,7 +128,7 @@ func TokenomicsKeeperWithActorAddrs(t testing.TB) ( supplier := sharedtypes.Supplier{ OwnerAddress: supplierOwnerAddr, OperatorAddress: supplierOwnerAddr, - Stake: &sdk.Coin{Denom: "upokt", Amount: sdkmath.NewInt(100000)}, + Stake: &sdk.Coin{Denom: "upokt", Amount: cosmosmath.NewInt(100000)}, Services: []*sharedtypes.SupplierServiceConfig{ { ServiceId: service.Id, @@ -351,9 +351,9 @@ func NewTokenomicsModuleKeepers( require.NoError(t, bankKeeper.SetParams(sdkCtx, banktypes.DefaultParams())) // Provide some initial funds to the suppliers & applications module accounts. - err = bankKeeper.MintCoins(sdkCtx, suppliertypes.ModuleName, sdk.NewCoins(sdk.NewCoin("upokt", sdkmath.NewInt(1000000000000)))) + err = bankKeeper.MintCoins(sdkCtx, suppliertypes.ModuleName, sdk.NewCoins(sdk.NewCoin("upokt", cosmosmath.NewInt(1000000000000)))) require.NoError(t, err) - err = bankKeeper.MintCoins(sdkCtx, apptypes.ModuleName, sdk.NewCoins(sdk.NewCoin("upokt", sdkmath.NewInt(1000000000000)))) + err = bankKeeper.MintCoins(sdkCtx, apptypes.ModuleName, sdk.NewCoins(sdk.NewCoin("upokt", cosmosmath.NewInt(1000000000000)))) require.NoError(t, err) // Construct a real shared keeper. @@ -519,17 +519,24 @@ func WithProposerAddr(addr string) TokenomicsModuleKeepersOpt { } } -// WithProofRequirement is an option to set the proof requirement in the tokenomics module keepers. +// WithProofRequirement is an option to enable or disable the proof requirement +// in the tokenomics module keepers by setting the proof request probability to +// 1 or 0, respectively whie setting the proof requirement threshold to 0 or +// MaxInt64, respectively. func WithProofRequirement(proofRequired bool) TokenomicsModuleKeepersOpt { return func(ctx context.Context, keepers *TokenomicsModuleKeepers) context.Context { proofParams := keepers.ProofKeeper.GetParams(ctx) if proofRequired { + // Require a proof 100% of the time probabilistically speaking. proofParams.ProofRequestProbability = 1 + // Require a proof of any claim amount (i.e. anything greater than 0). proofRequirementThreshold := cosmostypes.NewInt64Coin(volatile.DenomuPOKT, 0) proofParams.ProofRequirementThreshold = &proofRequirementThreshold } else { + // Never require a proof probabilistically speaking. proofParams.ProofRequestProbability = 0 + // Require a proof for MaxInt64 claim amount (i.e. should never trigger). proofRequirementThreshold := cosmostypes.NewInt64Coin(volatile.DenomuPOKT, math.MaxInt64) proofParams.ProofRequirementThreshold = &proofRequirementThreshold } diff --git a/x/tokenomics/keeper/settle_pending_claims.go b/x/tokenomics/keeper/settle_pending_claims.go index 91b1afdba..5bf90a83d 100644 --- a/x/tokenomics/keeper/settle_pending_claims.go +++ b/x/tokenomics/keeper/settle_pending_claims.go @@ -1,6 +1,7 @@ package keeper import ( + "context" "fmt" "cosmossdk.io/math" @@ -37,23 +38,12 @@ func (k Keeper) SettlePendingClaims(ctx sdk.Context) ( } // Capture the applications initial stake which will be used to calculate the - // max share any claim could receive from the application stake. - // This ensures that each claim can calculate the maximum amount it can take + // max share any claim could burn from the application stake. + // This ensures that each supplier can calculate the maximum amount it can take // from an application's stake. - applicationInitialStakeMap := make(map[string]sdk.Coin) - for _, claim := range expiringClaims { - appAddress := claim.SessionHeader.ApplicationAddress - if _, isAppFound := applicationInitialStakeMap[appAddress]; isAppFound { - continue - } - - app, isAppFound := k.applicationKeeper.GetApplication(ctx, appAddress) - if !isAppFound { - err = apptypes.ErrAppNotFound.Wrapf("application address: %q", appAddress) - return settledResult, expiredResult, err - } - - applicationInitialStakeMap[appAddress] = *app.GetStake() + applicationInitialStakeMap, err := k.getApplicationInitialStakeMap(ctx, expiringClaims) + if err != nil { + return settledResult, expiredResult, err } blockHeight := ctx.BlockHeight() @@ -197,8 +187,8 @@ func (k Keeper) SettlePendingClaims(ctx sdk.Context) ( // 1. The claim does not require a proof. // 2. The claim requires a proof and a valid proof was found. - claimApplication := claim.SessionHeader.ApplicationAddress - applicationInitialStake := applicationInitialStakeMap[claimApplication] + appAddress := claim.GetSessionHeader().GetApplicationAddress() + applicationInitialStake := applicationInitialStakeMap[appAddress] // Manage the mint & burn accounting for the claim. if err = k.ProcessTokenLogicModules(ctx, &claim, applicationInitialStake); err != nil { @@ -426,3 +416,34 @@ func (k Keeper) slashSupplierStake( return nil } + +// getApplicationInitialStakeMap returns a map from an application address to the +// initial stake of the application. This is used to calculate the maximum share +// any claim could burn from the application stake. +func (k Keeper) getApplicationInitialStakeMap( + ctx context.Context, + expiringClaims []prooftypes.Claim, +) (applicationInitialStakeMap map[string]sdk.Coin, err error) { + applicationInitialStakeMap = make(map[string]sdk.Coin) + for _, claim := range expiringClaims { + appAddress := claim.SessionHeader.ApplicationAddress + // The same application is participating in other claims being settled, + // so we already capture its initial stake. + if _, isAppFound := applicationInitialStakeMap[appAddress]; isAppFound { + continue + } + + app, isAppFound := k.applicationKeeper.GetApplication(ctx, appAddress) + if !isAppFound { + err := apptypes.ErrAppNotFound.Wrapf( + "trying to settle a claim for an application that does not exist (which should never happen) with address: %q", + appAddress, + ) + return nil, err + } + + applicationInitialStakeMap[appAddress] = *app.GetStake() + } + + return applicationInitialStakeMap, nil +} diff --git a/x/tokenomics/keeper/token_logic_modules.go b/x/tokenomics/keeper/token_logic_modules.go index 0dac283f6..53aca833b 100644 --- a/x/tokenomics/keeper/token_logic_modules.go +++ b/x/tokenomics/keeper/token_logic_modules.go @@ -27,8 +27,10 @@ import ( var ( // Governance parameters for the TLMGlobalMint module - // TODO_UPNEXT(@olshansk, #732): Make this a governance parameter and give it a non-zero value + tests. - MintPerClaimedTokenGlobalInflation = 0.1 + // TODO_BETA(@red-0ne, #732): Make this a governance parameter and give it a non-zero value + tests. + // GlobalInflationPerClaim is the percentage of the claim amount that is minted + // by TLMGlobalMint to reward the actors in the network. + GlobalInflationPerClaim = 0.1 ) const ( @@ -128,7 +130,7 @@ func init() { _, hasGlobalMintTLM := tokenLogicModuleProcessorMap[TLMGlobalMint] _, hasGlobalMintReimbursementRequestTLM := tokenLogicModuleProcessorMap[TLMGlobalMintReimbursementRequest] if hasGlobalMintTLM != hasGlobalMintReimbursementRequestTLM { - panic("TLMGlobalMint and TLMGlobalMintReimbursementRequest must be activated together") + panic("TLMGlobalMint and TLMGlobalMintReimbursementRequest must be (de-)activated together") } } @@ -419,13 +421,13 @@ func (k Keeper) TokenLogicModuleGlobalMint( ) error { logger := k.Logger().With("method", "TokenLogicModuleGlobalMint") - if MintPerClaimedTokenGlobalInflation == 0 { + if GlobalInflationPerClaim == 0 { logger.Warn("global inflation is set to zero. Skipping Global Mint TLM.") return nil } // Determine how much new uPOKT to mint based on global inflation - newMintCoin, newMintAmtFloat := calculateGlobalPerClaimMintInflationFromSettlementAmount(settlementCoin) + newMintCoin, newMintAmtFloat := CalculateGlobalPerClaimMintInflationFromSettlementAmount(settlementCoin) if newMintCoin.Amount.Int64() == 0 { return tokenomicstypes.ErrTokenomicsMintAmountZero } @@ -509,29 +511,43 @@ func (k Keeper) TokenLogicModuleGlobalMintReimbursementRequest( logger := k.Logger().With("method", "TokenLogicModuleGlobalMintReimbursementRequest") // Do not process the reimbursement request if there is no global inflation. - if MintPerClaimedTokenGlobalInflation == 0 { + if GlobalInflationPerClaim == 0 { logger.Warn("global inflation is set to zero. Skipping Global Mint Reimbursement Request TLM.") return nil } // Determine how much new uPOKT to mint based on global inflation - newMintCoin, _ := calculateGlobalPerClaimMintInflationFromSettlementAmount(actualSettlementCoin) + newMintCoin, _ := CalculateGlobalPerClaimMintInflationFromSettlementAmount(actualSettlementCoin) if newMintCoin.Amount.Int64() == 0 { return tokenomicstypes.ErrTokenomicsMintAmountZero } - // Update the application's on-chain stake - // This should not fall below zero since `ensureClaimAmountLimits` should have - // already checked and adjusted the settlement amount so that the application - // stake covers the global inflation. - newAppStake := application.Stake.Sub(newMintCoin) + newAppStake, err := application.Stake.SafeSub(newMintCoin) + // This should THEORETICALLY NEVER fall below zero. + // `ensureClaimAmountLimits` should have already checked and adjusted the settlement + // amount so that the application stake covers the global inflation. + if err != nil { + return err + } application.Stake = &newAppStake logger.Info(fmt.Sprintf("updated application %q stake to %s", application.Address, newAppStake)) + globalInflationMintedCoinsForClaim := sdk.NewCoins(newMintCoin) + + // Send the global per claim mint inflation uPOKT from the tokenomics module + // account to PNF/DAO. + daoAccountAddr, err := cosmostypes.AccAddressFromBech32(k.GetAuthority()) + if err != nil { + return tokenomicstypes.ErrTokenomicsApplicationReimbursementRequestFailed.Wrapf( + "getting PNF/DAO address: %v", + err, + ) + } + // Send the global per claim mint inflation uPOKT from the application module - // account to the tokenomics module account. + // account to the tokenomics module account as an intermediary step. if err := k.bankKeeper.SendCoinsFromModuleToModule( - ctx, apptypes.ModuleName, tokenomicstypes.ModuleName, sdk.NewCoins(newMintCoin), + ctx, apptypes.ModuleName, tokenomicstypes.ModuleName, globalInflationMintedCoinsForClaim, ); err != nil { return tokenomicstypes.ErrTokenomicsApplicationReimbursementRequestFailed.Wrapf( "sending %s from the application module account to the tokenomics module account: %v", @@ -544,16 +560,10 @@ func (k Keeper) TokenLogicModuleGlobalMintReimbursementRequest( )) // Send the global per claim mint inflation uPOKT from the tokenomics module - // account to PNF/DAO. - daoAccountAddr, err := cosmostypes.AccAddressFromBech32(k.GetAuthority()) - if err != nil { - return tokenomicstypes.ErrTokenomicsApplicationReimbursementRequestFailed.Wrapf( - "getting PNF/DAO address: %v", - err, - ) - } + // for second order economic effects. + // See: https://discord.com/channels/824324475256438814/997192534168182905/1299372745632649408 if err := k.bankKeeper.SendCoinsFromModuleToAccount( - ctx, tokenomicstypes.ModuleName, daoAccountAddr, sdk.NewCoins(newMintCoin), + ctx, tokenomicstypes.ModuleName, daoAccountAddr, globalInflationMintedCoinsForClaim, ); err != nil { return tokenomicstypes.ErrTokenomicsApplicationReimbursementRequestFailed.Wrapf( "sending %s from the tokenomics module account to the PNF/DAO account: %v", @@ -561,7 +571,9 @@ func (k Keeper) TokenLogicModuleGlobalMintReimbursementRequest( ) } - // Prepare and emit the event for the application being overcharged. + // Prepare and emit the event for the application that'll required reimbursement. + // Recall that it is being overcharged to compoensate for global inflation while + // preventing self-dealing attacks. reimbursementRequestEvent := &tokenomicstypes.EventApplicationReimbursementRequest{ ApplicationAddr: application.Address, SupplierOperatorAddr: supplier.OperatorAddress, @@ -573,10 +585,13 @@ func (k Keeper) TokenLogicModuleGlobalMintReimbursementRequest( eventManger := cosmostypes.UnwrapSDKContext(ctx).EventManager() if err := eventManger.EmitTypedEvent(reimbursementRequestEvent); err != nil { - return tokenomicstypes.ErrTokenomicsEmittingEventFailed.Wrapf( + err = tokenomicstypes.ErrTokenomicsEmittingEventFailed.Wrapf( "(%+v): %s", reimbursementRequestEvent, err, ) + + logger.Error(err.Error()) + return err } return nil @@ -655,8 +670,6 @@ func (k Keeper) sendRewardsToAccount( // If this is not the case, then the supplier essentially did "free work" and the // actual claim amount is less than what was claimed. // Ref: https://arxiv.org/pdf/2305.10672 -// TODO_TEST: Add more tests for edge cases that exercise all the code paths -// actualSettlementCoins could be updated in this function. func (k Keeper) ensureClaimAmountLimits( ctx context.Context, logger log.Logger, @@ -679,10 +692,10 @@ func (k Keeper) ensureClaimAmountLimits( // The application should have enough stake to cover for the global mint reimbursement. // This amount is deducted from the maximum claimable amount. - globalInflationCoin, _ := calculateGlobalPerClaimMintInflationFromSettlementAmount(claimSettlementCoin) + globalInflationCoin, _ := CalculateGlobalPerClaimMintInflationFromSettlementAmount(claimSettlementCoin) globalInflationAmt := globalInflationCoin.Amount - stakeRequirementAmt := claimSettlementCoin.Amount.Add(globalInflationAmt) - totalClaimedCoin := sdk.NewCoin(volatile.DenomuPOKT, stakeRequirementAmt) + minRequiredAppStakeAmt := claimSettlementCoin.Amount.Add(globalInflationAmt) + totalClaimedCoin := sdk.NewCoin(volatile.DenomuPOKT, minRequiredAppStakeAmt) // TODO_BETA(@red-0ne): Introduce a session sliding window to account for potential consumption // during the current session (i.e. Not the session being settled) such as: @@ -703,15 +716,18 @@ func (k Keeper) ensureClaimAmountLimits( // and assume maxClaimableAmt will be settled in session 2. // - Guarantee no over-servicing at the cost of higher application stake requirements. maxClaimableAmt := appStake.Amount.Quo(math.NewInt(sessionkeeper.NumSupplierPerSession)) - maxClaimSettlementAmt := stakeToMaxSettlementAmount(maxClaimableAmt) + maxClaimSettlementAmt := stakeShareToMaxSettlementAmount(maxClaimableAmt) // Check if the claimable amount is capped by the max claimable amount. - if stakeRequirementAmt.GT(maxClaimableAmt) { + // As per the Relay Mining paper, the Supplier claim MUST NO exceed the application's + // allocated stake. If it does, the claim is capped by the application's allocated stake + // and the supplier is effectively "overserviced". + if minRequiredAppStakeAmt.GT(maxClaimableAmt) { logger.Warn(fmt.Sprintf("Claim by supplier %s EXCEEDS LIMITS for application %s. Max claimable amount < Claim amount: %v < %v", supplier.GetOperatorAddress(), application.GetAddress(), maxClaimableAmt, claimSettlementCoin.Amount)) - stakeRequirementAmt = maxClaimableAmt - maxClaimSettlementAmt = stakeToMaxSettlementAmount(stakeRequirementAmt) + minRequiredAppStakeAmt = maxClaimableAmt + maxClaimSettlementAmt = stakeShareToMaxSettlementAmount(minRequiredAppStakeAmt) } // Nominal case: The claimable amount is within the limits set by Relay Mining. @@ -797,14 +813,15 @@ func (k Keeper) distributeSupplierRewardsToShareHolders( return nil } -// calculateGlobalPerClaimMintInflationFromSettlementAmount calculates the amount +// CalculateGlobalPerClaimMintInflationFromSettlementAmount calculates the amount // of uPOKT to mint based on the global per claim inflation rate as a function of // the settlement amount for a particular claim(s) or session(s). -func calculateGlobalPerClaimMintInflationFromSettlementAmount(settlementCoin sdk.Coin) (sdk.Coin, big.Float) { +// DEV_NOTE: This function is publically exposed to be used in the tests. +func CalculateGlobalPerClaimMintInflationFromSettlementAmount(settlementCoin sdk.Coin) (sdk.Coin, big.Float) { // Determine how much new uPOKT to mint based on global per claim inflation. // TODO_MAINNET: Consider using fixed point arithmetic for deterministic results. settlementAmtFloat := new(big.Float).SetUint64(settlementCoin.Amount.Uint64()) - newMintAmtFloat := new(big.Float).Mul(settlementAmtFloat, big.NewFloat(MintPerClaimedTokenGlobalInflation)) + newMintAmtFloat := new(big.Float).Mul(settlementAmtFloat, big.NewFloat(GlobalInflationPerClaim)) // DEV_NOTE: If new mint is less than 1 and more than 0, ceil it to 1 so that // we never expect to process a claim with 0 minted tokens. if newMintAmtFloat.Cmp(big.NewFloat(1)) < 0 && newMintAmtFloat.Cmp(big.NewFloat(0)) > 0 { @@ -815,16 +832,16 @@ func calculateGlobalPerClaimMintInflationFromSettlementAmount(settlementCoin sdk return mintAmtCoin, *newMintAmtFloat } -// stakeToMaxSettlementAmount calculates the max amount of uPOKT to that the supplier +// stakeShareToMaxSettlementAmount calculates the max amount of uPOKT to that the supplier // can claim based on the stake share and the global inflation allocation percentage. -// This is the inverse of calculateGlobalPerClaimMintInflationFromSettlementAmount. +// This is the inverse of CalculateGlobalPerClaimMintInflationFromSettlementAmount: // stake = maxSettlementAmt + globalInflationAmt // stake = maxSettlementAmt + (maxSettlementAmt * MintPerClaimedTokenGlobalInflation) // stake = maxSettlementAmt * (1 + MintPerClaimedTokenGlobalInflation) // maxSettlementAmt = stake / (1 + MintPerClaimedTokenGlobalInflation) -func stakeToMaxSettlementAmount(stakeShare math.Int) math.Int { +func stakeShareToMaxSettlementAmount(stakeShare math.Int) math.Int { stakeSahreFloat := big.NewFloat(0).SetInt(stakeShare.BigInt()) - maxSettlementAmountFloat := big.NewFloat(0).Quo(stakeSahreFloat, big.NewFloat(1+MintPerClaimedTokenGlobalInflation)) + maxSettlementAmountFloat := big.NewFloat(0).Quo(stakeSahreFloat, big.NewFloat(1+GlobalInflationPerClaim)) settlementAmount, _ := maxSettlementAmountFloat.Int(nil) return math.NewIntFromBigInt(settlementAmount) diff --git a/x/tokenomics/keeper/token_logic_modules_test.go b/x/tokenomics/keeper/token_logic_modules_test.go index 51bd4e46a..817442d01 100644 --- a/x/tokenomics/keeper/token_logic_modules_test.go +++ b/x/tokenomics/keeper/token_logic_modules_test.go @@ -4,10 +4,10 @@ import ( "bytes" "context" "fmt" - math2 "math" + "math" "testing" - "cosmossdk.io/math" + cosmosmath "cosmossdk.io/math" cosmostypes "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -43,8 +43,8 @@ func init() { func TestProcessTokenLogicModules_TLMBurnEqualsMint_Valid(t *testing.T) { // Test Parameters - appInitialStake := apptypes.DefaultMinStake.Amount.Mul(math.NewInt(2)) - supplierInitialStake := math.NewInt(1000000) + appInitialStake := apptypes.DefaultMinStake.Amount.Mul(cosmosmath.NewInt(2)) + supplierInitialStake := cosmosmath.NewInt(1000000) supplierRevShareRatios := []float32{12.5, 37.5, 50} globalComputeUnitsToTokensMultiplier := uint64(1) serviceComputeUnitsPerRelay := uint64(1) @@ -57,7 +57,7 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMint_Valid(t *testing.T) { // Ensure the claim is within relay mining bounds numTokensClaimed := int64(numRelays * serviceComputeUnitsPerRelay * globalComputeUnitsToTokensMultiplier) - maxClaimableAmountPerSupplier := appInitialStake.Quo(math.NewInt(sessionkeeper.NumSupplierPerSession)) + maxClaimableAmountPerSupplier := appInitialStake.Quo(cosmosmath.NewInt(sessionkeeper.NumSupplierPerSession)) require.GreaterOrEqual(t, maxClaimableAmountPerSupplier.Int64(), numTokensClaimed) // Retrieve the app and supplier module addresses @@ -71,10 +71,10 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMint_Valid(t *testing.T) { require.NoError(t, err) // TODO_TECHDEBT: Setting inflation to zero so we are testing the BurnEqualsMint logic exclusively. // Once it is a governance param, update it using the keeper above. - prevInflationValue := tokenomicskeeper.MintPerClaimedTokenGlobalInflation - tokenomicskeeper.MintPerClaimedTokenGlobalInflation = 0 + prevInflationValue := tokenomicskeeper.GlobalInflationPerClaim + tokenomicskeeper.GlobalInflationPerClaim = 0 t.Cleanup(func() { - tokenomicskeeper.MintPerClaimedTokenGlobalInflation = prevInflationValue + tokenomicskeeper.GlobalInflationPerClaim = prevInflationValue }) // Add a new application with non-zero app stake end balance to assert against. @@ -127,7 +127,7 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMint_Valid(t *testing.T) { require.EqualValues(t, appStartBalance, appEndBalance) // Determine the expected app end stake amount and the expected app burn - appBurn := math.NewInt(numTokensClaimed) + appBurn := cosmosmath.NewInt(numTokensClaimed) expectedAppEndStakeAmount := appInitialStake.Sub(appBurn) // Assert that `applicationAddress` staked balance has decreased by the appropriate amount @@ -173,7 +173,7 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMint_Valid_SupplierExceedsMaxClai serviceComputeUnitsPerRelay := uint64(100) service := prepareTestService(serviceComputeUnitsPerRelay) numRelays := uint64(1000) // By a single supplier for application in this session - supplierInitialStake := math.NewInt(1000000) + supplierInitialStake := cosmosmath.NewInt(1000000) supplierRevShareRatios := []float32{12.5, 37.5, 50} // Prepare the keepers @@ -184,7 +184,7 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMint_Valid_SupplierExceedsMaxClai // Determine the max a supplier can claim maxClaimableAmountPerSupplier := int64(numRelays * serviceComputeUnitsPerRelay * globalComputeUnitsToTokensMultiplier) // Figure out what the app's initial stake should be to cover the max claimable amount - appInitialStake := math.NewInt(maxClaimableAmountPerSupplier*sessionkeeper.NumSupplierPerSession + 1) + appInitialStake := cosmosmath.NewInt(maxClaimableAmountPerSupplier*sessionkeeper.NumSupplierPerSession + 1) // Increase the number of relay such that the supplier did "free work" and would // be able to claim more than the max claimable amount. numRelays *= 5 @@ -201,10 +201,10 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMint_Valid_SupplierExceedsMaxClai require.NoError(t, err) // TODO_TECHDEBT: Setting inflation to zero so we are testing the BurnEqualsMint logic exclusively. // Once it is a governance param, update it using the keeper above. - prevInflationValue := tokenomicskeeper.MintPerClaimedTokenGlobalInflation - tokenomicskeeper.MintPerClaimedTokenGlobalInflation = 0 + prevInflationValue := tokenomicskeeper.GlobalInflationPerClaim + tokenomicskeeper.GlobalInflationPerClaim = 0 t.Cleanup(func() { - tokenomicskeeper.MintPerClaimedTokenGlobalInflation = prevInflationValue + tokenomicskeeper.GlobalInflationPerClaim = prevInflationValue }) // Add a new application with non-zero app stake end balance to assert against. @@ -257,7 +257,7 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMint_Valid_SupplierExceedsMaxClai require.EqualValues(t, appStartBalance, appEndBalance) // Determine the expected app end stake amount and the expected app burn - appBurn := math.NewInt(maxClaimableAmountPerSupplier) + appBurn := cosmosmath.NewInt(maxClaimableAmountPerSupplier) appBurnCoin := sdk.NewCoin(volatile.DenomuPOKT, appBurn) expectedAppEndStakeAmount := appInitialStake.Sub(appBurn) @@ -314,8 +314,8 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMint_Valid_SupplierExceedsMaxClai func TestProcessTokenLogicModules_TLMGlobalMint_Valid_MintDistributionCorrect(t *testing.T) { // Test Parameters - appInitialStake := apptypes.DefaultMinStake.Amount.Mul(math.NewInt(2)) - supplierInitialStake := math.NewInt(1000000) + appInitialStake := apptypes.DefaultMinStake.Amount.Mul(cosmosmath.NewInt(2)) + supplierInitialStake := cosmosmath.NewInt(1000000) supplierRevShareRatios := []float32{12.5, 37.5, 50} globalComputeUnitsToTokensMultiplier := uint64(1) serviceComputeUnitsPerRelay := uint64(1) @@ -399,12 +399,12 @@ func TestProcessTokenLogicModules_TLMGlobalMint_Valid_MintDistributionCorrect(t } // Compute mint per actor - numTokensMinted := numTokensClaimed * tokenomicskeeper.MintPerClaimedTokenGlobalInflation - numTokensMintedInt := math.NewIntFromUint64(uint64(numTokensMinted)) - daoMint := math.NewInt(int64(numTokensMinted * tokenomicskeeper.MintAllocationDAO)) - propMint := math.NewInt(int64(numTokensMinted * tokenomicskeeper.MintAllocationProposer)) - serviceOwnerMint := math.NewInt(int64(numTokensMinted * tokenomicskeeper.MintAllocationSourceOwner)) - appMint := math.NewInt(int64(numTokensMinted * tokenomicskeeper.MintAllocationApplication)) + numTokensMinted := numTokensClaimed * tokenomicskeeper.GlobalInflationPerClaim + numTokensMintedInt := cosmosmath.NewIntFromUint64(uint64(numTokensMinted)) + daoMint := cosmosmath.NewInt(int64(numTokensMinted * tokenomicskeeper.MintAllocationDAO)) + propMint := cosmosmath.NewInt(int64(numTokensMinted * tokenomicskeeper.MintAllocationProposer)) + serviceOwnerMint := cosmosmath.NewInt(int64(numTokensMinted * tokenomicskeeper.MintAllocationSourceOwner)) + appMint := cosmosmath.NewInt(int64(numTokensMinted * tokenomicskeeper.MintAllocationApplication)) supplierMint := float32(numTokensMinted * tokenomicskeeper.MintAllocationSupplier) // Ensure the balance was increase be the appropriate amount @@ -418,7 +418,7 @@ func TestProcessTokenLogicModules_TLMGlobalMint_Valid_MintDistributionCorrect(t balanceAfter := supplierShareholderBalancesAfter[addr].Amount.Int64() mintShare := int64(supplierMint * revShare.RevSharePercentage / 100) rewardShare := int64(float32(numTokensClaimed) * revShare.RevSharePercentage / 100) - balanceIncrease := math.NewInt(mintShare + rewardShare) + balanceIncrease := cosmosmath.NewInt(mintShare + rewardShare) expectedBalanceAfter := balanceBefore.Amount.Add(balanceIncrease).Int64() // TODO_MAINNET: Remove the InDelta check and use the exact amount once the floating point arithmetic is fixed acceptableRoundingDelta := tokenomicskeeper.MintDistributionAllowableTolerancePercent * float64(balanceAfter) @@ -429,7 +429,7 @@ func TestProcessTokenLogicModules_TLMGlobalMint_Valid_MintDistributionCorrect(t require.True(t, appFound) appStakeAfter := foundApp.GetStake().Amount - numTokensClaimedInt := math.NewIntFromUint64(uint64(numTokensClaimed)) + numTokensClaimedInt := cosmosmath.NewIntFromUint64(uint64(numTokensClaimed)) require.Equal(t, appInitialStake.Sub(numTokensMintedInt).Sub(numTokensClaimedInt), appStakeAfter) } @@ -452,7 +452,7 @@ func TestProcessTokenLogicModules_AppNotFound(t *testing.T) { } // Process the token logic modules - err := keeper.ProcessTokenLogicModules(ctx, &claim, uPOKTCoin(math2.MaxInt)) + err := keeper.ProcessTokenLogicModules(ctx, &claim, uPOKTCoin(math.MaxInt)) require.Error(t, err) require.ErrorIs(t, err, tokenomicstypes.ErrTokenomicsApplicationNotFound) } @@ -475,7 +475,7 @@ func TestProcessTokenLogicModules_ServiceNotFound(t *testing.T) { } // Execute test function - err := keeper.ProcessTokenLogicModules(ctx, &claim, uPOKTCoin(math2.MaxInt)) + err := keeper.ProcessTokenLogicModules(ctx, &claim, uPOKTCoin(math.MaxInt)) require.Error(t, err) require.ErrorIs(t, err, tokenomicstypes.ErrTokenomicsServiceNotFound) @@ -545,7 +545,7 @@ func TestProcessTokenLogicModules_InvalidRoot(t *testing.T) { claim.RootHash = smt.MerkleRoot(test.root[:]) // Execute test function - err := keeper.ProcessTokenLogicModules(ctx, &claim, uPOKTCoin(math2.MaxInt)) + err := keeper.ProcessTokenLogicModules(ctx, &claim, uPOKTCoin(math.MaxInt)) // Assert the error if test.errExpected { @@ -635,7 +635,7 @@ func TestProcessTokenLogicModules_InvalidClaim(t *testing.T) { err = fmt.Errorf("panic occurred: %v", r) } }() - return keeper.ProcessTokenLogicModules(ctx, test.claim, uPOKTCoin(math2.MaxInt)) + return keeper.ProcessTokenLogicModules(ctx, test.claim, uPOKTCoin(math.MaxInt)) }() // Assert the error @@ -649,6 +649,18 @@ func TestProcessTokenLogicModules_InvalidClaim(t *testing.T) { } } +func TestProcessTokenLogicModules_AppStakeMissingGlobalInflationAmount(t *testing.T) { + t.Skip("TODO: Test application stake that does not cover the global inflation amount") +} + +func TestProcessTokenLogicModules_ZeroAppStakeShareDueToPrecisionLoss(t *testing.T) { + t.Skip("TODO: Test application stake that is low enough to have a zero share due to precision loss") +} + +func TestProcessTokenLogicModules_AppStakeGoesBelowMinStake(t *testing.T) { + t.Skip("TODO: Test application stake that goes min stake") +} + // prepareTestClaim uses the given number of relays and compute unit per relay in the // service provided to set up the test claim correctly. func prepareTestClaim( From 2bd72405fa1e95af1ec50169513459bba60bd97d Mon Sep 17 00:00:00 2001 From: Redouane Lakrache Date: Wed, 30 Oct 2024 19:17:12 +0100 Subject: [PATCH 30/31] chore: Address review change requests --- x/tokenomics/keeper/token_logic_modules.go | 14 ++++++++------ x/tokenomics/keeper/token_logic_modules_test.go | 12 ++++++------ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/x/tokenomics/keeper/token_logic_modules.go b/x/tokenomics/keeper/token_logic_modules.go index db3b48dbb..8eca626a9 100644 --- a/x/tokenomics/keeper/token_logic_modules.go +++ b/x/tokenomics/keeper/token_logic_modules.go @@ -525,6 +525,7 @@ func (k Keeper) TokenLogicModuleGlobalMintReimbursementRequest( // This should THEORETICALLY NEVER fall below zero. // `ensureClaimAmountLimits` should have already checked and adjusted the settlement // amount so that the application stake covers the global inflation. + // TODO_POST_MAINNET: Consider removing this since it should never happen just to simplify the code if err != nil { return err } @@ -715,10 +716,10 @@ func (k Keeper) ensureClaimAmountLimits( // and assume maxClaimableAmt will be settled in session 2. // - Guarantee no over-servicing at the cost of higher application stake requirements. maxClaimableAmt := appStake.Amount.Quo(math.NewInt(sessionkeeper.NumSupplierPerSession)) - maxClaimSettlementAmt := stakeShareToMaxSettlementAmount(maxClaimableAmt) + maxClaimSettlementAmt := supplierAppStakeToMaxSettlementAmount(maxClaimableAmt) // Check if the claimable amount is capped by the max claimable amount. - // As per the Relay Mining paper, the Supplier claim MUST NO exceed the application's + // As per the Relay Mining paper, the Supplier claim MUST NOT exceed the application's // allocated stake. If it does, the claim is capped by the application's allocated stake // and the supplier is effectively "overserviced". if minRequiredAppStakeAmt.GT(maxClaimableAmt) { @@ -726,7 +727,7 @@ func (k Keeper) ensureClaimAmountLimits( supplier.GetOperatorAddress(), application.GetAddress(), maxClaimableAmt, claimSettlementCoin.Amount)) minRequiredAppStakeAmt = maxClaimableAmt - maxClaimSettlementAmt = stakeShareToMaxSettlementAmount(minRequiredAppStakeAmt) + maxClaimSettlementAmt = supplierAppStakeToMaxSettlementAmount(minRequiredAppStakeAmt) } // Nominal case: The claimable amount is within the limits set by Relay Mining. @@ -831,14 +832,15 @@ func CalculateGlobalPerClaimMintInflationFromSettlementAmount(settlementCoin sdk return mintAmtCoin, *newMintAmtFloat } -// stakeShareToMaxSettlementAmount calculates the max amount of uPOKT to that the supplier -// can claim based on the stake share and the global inflation allocation percentage. +// supplierAppStakeToMaxSettlementAmount calculates the max amount of uPOKT the supplier +// can claim based on the stake allocated to the supplier and the global inflation +// allocation percentage. // This is the inverse of CalculateGlobalPerClaimMintInflationFromSettlementAmount: // stake = maxSettlementAmt + globalInflationAmt // stake = maxSettlementAmt + (maxSettlementAmt * MintPerClaimedTokenGlobalInflation) // stake = maxSettlementAmt * (1 + MintPerClaimedTokenGlobalInflation) // maxSettlementAmt = stake / (1 + MintPerClaimedTokenGlobalInflation) -func stakeShareToMaxSettlementAmount(stakeShare math.Int) math.Int { +func supplierAppStakeToMaxSettlementAmount(stakeShare math.Int) math.Int { stakeSahreFloat := big.NewFloat(0).SetInt(stakeShare.BigInt()) maxSettlementAmountFloat := big.NewFloat(0).Quo(stakeSahreFloat, big.NewFloat(1+GlobalInflationPerClaim)) diff --git a/x/tokenomics/keeper/token_logic_modules_test.go b/x/tokenomics/keeper/token_logic_modules_test.go index 817442d01..db5aa8320 100644 --- a/x/tokenomics/keeper/token_logic_modules_test.go +++ b/x/tokenomics/keeper/token_logic_modules_test.go @@ -649,16 +649,16 @@ func TestProcessTokenLogicModules_InvalidClaim(t *testing.T) { } } -func TestProcessTokenLogicModules_AppStakeMissingGlobalInflationAmount(t *testing.T) { - t.Skip("TODO: Test application stake that does not cover the global inflation amount") +func TestProcessTokenLogicModules_AppStakeInsufficientToCoverGlobalInflationAmount(t *testing.T) { + t.Skip("TODO_MAINNET(@red-0ne): Test application stake that is insufficient to cover the global inflation amount, for reimbursment and the max claim should scale down proportionally") } -func TestProcessTokenLogicModules_ZeroAppStakeShareDueToPrecisionLoss(t *testing.T) { - t.Skip("TODO: Test application stake that is low enough to have a zero share due to precision loss") +func TestProcessTokenLogicModules_AppStakeTooLowRoundingToZero(t *testing.T) { + t.Skip("TODO_MAINNET(@red-0ne): Test application stake that is too low which results in stake/num_suppliers rounding down to zero") } -func TestProcessTokenLogicModules_AppStakeGoesBelowMinStake(t *testing.T) { - t.Skip("TODO: Test application stake that goes min stake") +func TestProcessTokenLogicModules_AppStakeDropsBelowMinStakeAfterSession(t *testing.T) { + t.Skip("TODO_MAINNET(@red-0ne): Test that application stake being auto-unbonding after the stake drops below the required minimum when settling session accounting") } // prepareTestClaim uses the given number of relays and compute unit per relay in the From cef4dcb2059d9b36f6297b08dabdc4221b8018b0 Mon Sep 17 00:00:00 2001 From: Redouane Lakrache Date: Wed, 30 Oct 2024 20:27:42 +0100 Subject: [PATCH 31/31] fix: Rename function --- x/tokenomics/keeper/token_logic_modules.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x/tokenomics/keeper/token_logic_modules.go b/x/tokenomics/keeper/token_logic_modules.go index 8eca626a9..3dba9136a 100644 --- a/x/tokenomics/keeper/token_logic_modules.go +++ b/x/tokenomics/keeper/token_logic_modules.go @@ -840,9 +840,9 @@ func CalculateGlobalPerClaimMintInflationFromSettlementAmount(settlementCoin sdk // stake = maxSettlementAmt + (maxSettlementAmt * MintPerClaimedTokenGlobalInflation) // stake = maxSettlementAmt * (1 + MintPerClaimedTokenGlobalInflation) // maxSettlementAmt = stake / (1 + MintPerClaimedTokenGlobalInflation) -func supplierAppStakeToMaxSettlementAmount(stakeShare math.Int) math.Int { - stakeSahreFloat := big.NewFloat(0).SetInt(stakeShare.BigInt()) - maxSettlementAmountFloat := big.NewFloat(0).Quo(stakeSahreFloat, big.NewFloat(1+GlobalInflationPerClaim)) +func supplierAppStakeToMaxSettlementAmount(stakeAmount math.Int) math.Int { + stakeAmountFloat := big.NewFloat(0).SetInt(stakeAmount.BigInt()) + maxSettlementAmountFloat := big.NewFloat(0).Quo(stakeAmountFloat, big.NewFloat(1+GlobalInflationPerClaim)) settlementAmount, _ := maxSettlementAmountFloat.Int(nil) return math.NewIntFromBigInt(settlementAmount)