multinode/payouts: all satellites summaries added.

payout summaries for specific/all periods added.

Change-Id: I92087edec548c0418a0f543d643e59f5c7df9621
This commit is contained in:
Qweder93 2021-05-05 20:34:10 +03:00
parent 547a6e9930
commit 19561698ba
12 changed files with 794 additions and 76 deletions

View File

@ -96,6 +96,53 @@ func (controller *Payouts) Estimations(w http.ResponseWriter, r *http.Request) {
}
}
// PeriodSummary handles retrieval from nodes for specific period.
func (controller *Payouts) PeriodSummary(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
defer mon.Task()(&ctx)(&err)
segmentParams := mux.Vars(r)
w.Header().Add("Content-Type", "application/json")
period, ok := segmentParams["period"]
if !ok {
controller.serveError(w, http.StatusBadRequest, ErrPayouts.Wrap(err))
return
}
summary, err := controller.service.NodesPeriodSummary(ctx, period)
if err != nil {
controller.serveError(w, http.StatusInternalServerError, ErrPayouts.Wrap(err))
return
}
if err = json.NewEncoder(w).Encode(summary); err != nil {
controller.log.Error("failed to write json response", zap.Error(err))
return
}
}
// Summary handles retrieval from nodes.
func (controller *Payouts) Summary(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
defer mon.Task()(&ctx)(&err)
w.Header().Add("Content-Type", "application/json")
summary, err := controller.service.NodesSummary(ctx)
if err != nil {
controller.serveError(w, http.StatusInternalServerError, ErrPayouts.Wrap(err))
return
}
if err = json.NewEncoder(w).Encode(summary); err != nil {
controller.log.Error("failed to write json response", zap.Error(err))
return
}
}
// serveError set http statuses and send json error.
func (controller *Payouts) serveError(w http.ResponseWriter, status int, err error) {
w.WriteHeader(status)

View File

@ -75,6 +75,8 @@ func NewServer(log *zap.Logger, config Config, nodes *nodes.Service, payouts *pa
payoutsController := controllers.NewPayouts(server.log, server.payouts)
payoutsRouter := apiRouter.PathPrefix("/payouts").Subrouter()
payoutsRouter.HandleFunc("/summary/{period}", payoutsController.PeriodSummary).Methods(http.MethodGet)
payoutsRouter.HandleFunc("/summary", payoutsController.Summary).Methods(http.MethodGet)
payoutsRouter.HandleFunc("/total-earned", payoutsController.GetAllNodesTotalEarned).Methods(http.MethodGet)
payoutsRouter.HandleFunc("/estimations/{satelliteID}", payoutsController.SatelliteEstimations).Methods(http.MethodGet)
payoutsRouter.HandleFunc("/estimations", payoutsController.Estimations).Methods(http.MethodGet)

View File

@ -12,3 +12,18 @@ type SatelliteSummary struct {
SatelliteID storj.NodeID `json:"satelliteID"`
Earned int64 `json:"earned"`
}
// NodeSummary contains node's payout information.
type NodeSummary struct {
NodeID storj.NodeID `json:"nodeId"`
Held int64 `json:"held"`
Paid int64 `json:"paid"`
}
// Summary contains payouts page data.
type Summary struct {
TotalEarned int64 `json:"totalEarned"`
TotalHeld int64 `json:"totalHeld"`
TotalPaid int64 `json:"totalPaid"`
NodeSummary []NodeSummary `json:"nodeSummary"`
}

View File

@ -112,6 +112,120 @@ func (service *Service) GetAllNodesEarnedOnSatellite(ctx context.Context) (earne
return earned, nil
}
// NodesSummary returns all satellites all time stats.
func (service *Service) NodesSummary(ctx context.Context) (_ Summary, err error) {
defer mon.Task()(&ctx)(&err)
var summary Summary
list, err := service.nodes.List(ctx)
if err != nil {
return Summary{}, Error.Wrap(err)
}
for _, node := range list {
info, err := service.getAllSatellitesAllTime(ctx, node)
if err != nil {
return Summary{}, Error.Wrap(err)
}
summary.TotalPaid += info.Paid
summary.TotalHeld += info.Held
summary.NodeSummary = append(summary.NodeSummary, NodeSummary{
NodeID: node.ID,
Held: info.Held,
Paid: info.Paid,
})
}
summary.TotalEarned = summary.TotalPaid + summary.TotalHeld
return summary, nil
}
// NodesPeriodSummary returns all satellites stats for specific period.
func (service *Service) NodesPeriodSummary(ctx context.Context, period string) (_ Summary, err error) {
defer mon.Task()(&ctx)(&err)
var summary Summary
list, err := service.nodes.List(ctx)
if err != nil {
return Summary{}, Error.Wrap(err)
}
for _, node := range list {
info, err := service.getAllSatellitesPeriod(ctx, node, period)
if err != nil {
return Summary{}, Error.Wrap(err)
}
summary.TotalPaid += info.Paid
summary.TotalHeld += info.Held
summary.NodeSummary = append(summary.NodeSummary, NodeSummary{
NodeID: node.ID,
Held: info.Held,
Paid: info.Paid,
})
}
summary.TotalEarned = summary.TotalPaid + summary.TotalHeld
return summary, nil
}
func (service *Service) getAllSatellitesPeriod(ctx context.Context, node nodes.Node, period string) (info *multinodepb.PayoutInfo, err error) {
conn, err := service.dialer.DialNodeURL(ctx, storj.NodeURL{
ID: node.ID,
Address: node.PublicAddress,
})
if err != nil {
return &multinodepb.PayoutInfo{}, Error.Wrap(err)
}
defer func() {
err = errs.Combine(err, conn.Close())
}()
payoutClient := multinodepb.NewDRPCPayoutClient(conn)
header := &multinodepb.RequestHeader{
ApiKey: node.APISecret,
}
response, err := payoutClient.AllSatellitesPeriodSummary(ctx, &multinodepb.AllSatellitesPeriodSummaryRequest{Header: header, Period: period})
if err != nil {
return &multinodepb.PayoutInfo{}, Error.Wrap(err)
}
return response.PayoutInfo, nil
}
func (service *Service) getAllSatellitesAllTime(ctx context.Context, node nodes.Node) (info *multinodepb.PayoutInfo, err error) {
conn, err := service.dialer.DialNodeURL(ctx, storj.NodeURL{
ID: node.ID,
Address: node.PublicAddress,
})
if err != nil {
return &multinodepb.PayoutInfo{}, Error.Wrap(err)
}
defer func() {
err = errs.Combine(err, conn.Close())
}()
payoutClient := multinodepb.NewDRPCPayoutClient(conn)
header := &multinodepb.RequestHeader{
ApiKey: node.APISecret,
}
response, err := payoutClient.AllSatellitesSummary(ctx, &multinodepb.AllSatellitesSummaryRequest{Header: header})
if err != nil {
return &multinodepb.PayoutInfo{}, Error.Wrap(err)
}
return response.PayoutInfo, nil
}
// AllNodesSatelliteEstimations returns specific satellite all time estimated earnings.
func (service *Service) AllNodesSatelliteEstimations(ctx context.Context, satelliteID storj.NodeID) (_ int64, err error) {
defer mon.Task()(&ctx)(&err)

View File

@ -842,6 +842,166 @@ func (m *EstimatedPayoutTotalResponse) GetEstimatedEarnings() int64 {
return 0
}
type AllSatellitesSummaryRequest struct {
Header *RequestHeader `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *AllSatellitesSummaryRequest) Reset() { *m = AllSatellitesSummaryRequest{} }
func (m *AllSatellitesSummaryRequest) String() string { return proto.CompactTextString(m) }
func (*AllSatellitesSummaryRequest) ProtoMessage() {}
func (*AllSatellitesSummaryRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_9a45fd79b06f3a1b, []int{17}
}
func (m *AllSatellitesSummaryRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_AllSatellitesSummaryRequest.Unmarshal(m, b)
}
func (m *AllSatellitesSummaryRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_AllSatellitesSummaryRequest.Marshal(b, m, deterministic)
}
func (m *AllSatellitesSummaryRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_AllSatellitesSummaryRequest.Merge(m, src)
}
func (m *AllSatellitesSummaryRequest) XXX_Size() int {
return xxx_messageInfo_AllSatellitesSummaryRequest.Size(m)
}
func (m *AllSatellitesSummaryRequest) XXX_DiscardUnknown() {
xxx_messageInfo_AllSatellitesSummaryRequest.DiscardUnknown(m)
}
var xxx_messageInfo_AllSatellitesSummaryRequest proto.InternalMessageInfo
func (m *AllSatellitesSummaryRequest) GetHeader() *RequestHeader {
if m != nil {
return m.Header
}
return nil
}
type AllSatellitesSummaryResponse struct {
PayoutInfo *PayoutInfo `protobuf:"bytes,1,opt,name=payout_info,json=payoutInfo,proto3" json:"payout_info,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *AllSatellitesSummaryResponse) Reset() { *m = AllSatellitesSummaryResponse{} }
func (m *AllSatellitesSummaryResponse) String() string { return proto.CompactTextString(m) }
func (*AllSatellitesSummaryResponse) ProtoMessage() {}
func (*AllSatellitesSummaryResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_9a45fd79b06f3a1b, []int{18}
}
func (m *AllSatellitesSummaryResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_AllSatellitesSummaryResponse.Unmarshal(m, b)
}
func (m *AllSatellitesSummaryResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_AllSatellitesSummaryResponse.Marshal(b, m, deterministic)
}
func (m *AllSatellitesSummaryResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_AllSatellitesSummaryResponse.Merge(m, src)
}
func (m *AllSatellitesSummaryResponse) XXX_Size() int {
return xxx_messageInfo_AllSatellitesSummaryResponse.Size(m)
}
func (m *AllSatellitesSummaryResponse) XXX_DiscardUnknown() {
xxx_messageInfo_AllSatellitesSummaryResponse.DiscardUnknown(m)
}
var xxx_messageInfo_AllSatellitesSummaryResponse proto.InternalMessageInfo
func (m *AllSatellitesSummaryResponse) GetPayoutInfo() *PayoutInfo {
if m != nil {
return m.PayoutInfo
}
return nil
}
type AllSatellitesPeriodSummaryRequest struct {
Header *RequestHeader `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"`
Period string `protobuf:"bytes,2,opt,name=period,proto3" json:"period,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *AllSatellitesPeriodSummaryRequest) Reset() { *m = AllSatellitesPeriodSummaryRequest{} }
func (m *AllSatellitesPeriodSummaryRequest) String() string { return proto.CompactTextString(m) }
func (*AllSatellitesPeriodSummaryRequest) ProtoMessage() {}
func (*AllSatellitesPeriodSummaryRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_9a45fd79b06f3a1b, []int{19}
}
func (m *AllSatellitesPeriodSummaryRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_AllSatellitesPeriodSummaryRequest.Unmarshal(m, b)
}
func (m *AllSatellitesPeriodSummaryRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_AllSatellitesPeriodSummaryRequest.Marshal(b, m, deterministic)
}
func (m *AllSatellitesPeriodSummaryRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_AllSatellitesPeriodSummaryRequest.Merge(m, src)
}
func (m *AllSatellitesPeriodSummaryRequest) XXX_Size() int {
return xxx_messageInfo_AllSatellitesPeriodSummaryRequest.Size(m)
}
func (m *AllSatellitesPeriodSummaryRequest) XXX_DiscardUnknown() {
xxx_messageInfo_AllSatellitesPeriodSummaryRequest.DiscardUnknown(m)
}
var xxx_messageInfo_AllSatellitesPeriodSummaryRequest proto.InternalMessageInfo
func (m *AllSatellitesPeriodSummaryRequest) GetHeader() *RequestHeader {
if m != nil {
return m.Header
}
return nil
}
func (m *AllSatellitesPeriodSummaryRequest) GetPeriod() string {
if m != nil {
return m.Period
}
return ""
}
type AllSatellitesPeriodSummaryResponse struct {
PayoutInfo *PayoutInfo `protobuf:"bytes,1,opt,name=payout_info,json=payoutInfo,proto3" json:"payout_info,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *AllSatellitesPeriodSummaryResponse) Reset() { *m = AllSatellitesPeriodSummaryResponse{} }
func (m *AllSatellitesPeriodSummaryResponse) String() string { return proto.CompactTextString(m) }
func (*AllSatellitesPeriodSummaryResponse) ProtoMessage() {}
func (*AllSatellitesPeriodSummaryResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_9a45fd79b06f3a1b, []int{20}
}
func (m *AllSatellitesPeriodSummaryResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_AllSatellitesPeriodSummaryResponse.Unmarshal(m, b)
}
func (m *AllSatellitesPeriodSummaryResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_AllSatellitesPeriodSummaryResponse.Marshal(b, m, deterministic)
}
func (m *AllSatellitesPeriodSummaryResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_AllSatellitesPeriodSummaryResponse.Merge(m, src)
}
func (m *AllSatellitesPeriodSummaryResponse) XXX_Size() int {
return xxx_messageInfo_AllSatellitesPeriodSummaryResponse.Size(m)
}
func (m *AllSatellitesPeriodSummaryResponse) XXX_DiscardUnknown() {
xxx_messageInfo_AllSatellitesPeriodSummaryResponse.DiscardUnknown(m)
}
var xxx_messageInfo_AllSatellitesPeriodSummaryResponse proto.InternalMessageInfo
func (m *AllSatellitesPeriodSummaryResponse) GetPayoutInfo() *PayoutInfo {
if m != nil {
return m.PayoutInfo
}
return nil
}
type EarnedRequest struct {
Header *RequestHeader `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
@ -853,7 +1013,7 @@ func (m *EarnedRequest) Reset() { *m = EarnedRequest{} }
func (m *EarnedRequest) String() string { return proto.CompactTextString(m) }
func (*EarnedRequest) ProtoMessage() {}
func (*EarnedRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_9a45fd79b06f3a1b, []int{17}
return fileDescriptor_9a45fd79b06f3a1b, []int{21}
}
func (m *EarnedRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_EarnedRequest.Unmarshal(m, b)
@ -891,7 +1051,7 @@ func (m *EarnedResponse) Reset() { *m = EarnedResponse{} }
func (m *EarnedResponse) String() string { return proto.CompactTextString(m) }
func (*EarnedResponse) ProtoMessage() {}
func (*EarnedResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_9a45fd79b06f3a1b, []int{18}
return fileDescriptor_9a45fd79b06f3a1b, []int{22}
}
func (m *EarnedResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_EarnedResponse.Unmarshal(m, b)
@ -929,7 +1089,7 @@ func (m *EarnedPerSatelliteRequest) Reset() { *m = EarnedPerSatelliteReq
func (m *EarnedPerSatelliteRequest) String() string { return proto.CompactTextString(m) }
func (*EarnedPerSatelliteRequest) ProtoMessage() {}
func (*EarnedPerSatelliteRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_9a45fd79b06f3a1b, []int{19}
return fileDescriptor_9a45fd79b06f3a1b, []int{23}
}
func (m *EarnedPerSatelliteRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_EarnedPerSatelliteRequest.Unmarshal(m, b)
@ -967,7 +1127,7 @@ func (m *EarnedPerSatelliteResponse) Reset() { *m = EarnedPerSatelliteRe
func (m *EarnedPerSatelliteResponse) String() string { return proto.CompactTextString(m) }
func (*EarnedPerSatelliteResponse) ProtoMessage() {}
func (*EarnedPerSatelliteResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_9a45fd79b06f3a1b, []int{20}
return fileDescriptor_9a45fd79b06f3a1b, []int{24}
}
func (m *EarnedPerSatelliteResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_EarnedPerSatelliteResponse.Unmarshal(m, b)
@ -1006,7 +1166,7 @@ func (m *EarnedSatellite) Reset() { *m = EarnedSatellite{} }
func (m *EarnedSatellite) String() string { return proto.CompactTextString(m) }
func (*EarnedSatellite) ProtoMessage() {}
func (*EarnedSatellite) Descriptor() ([]byte, []int) {
return fileDescriptor_9a45fd79b06f3a1b, []int{21}
return fileDescriptor_9a45fd79b06f3a1b, []int{25}
}
func (m *EarnedSatellite) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_EarnedSatellite.Unmarshal(m, b)
@ -1033,6 +1193,52 @@ func (m *EarnedSatellite) GetTotal() int64 {
return 0
}
type PayoutInfo struct {
Held int64 `protobuf:"varint,1,opt,name=held,proto3" json:"held,omitempty"`
Paid int64 `protobuf:"varint,2,opt,name=paid,proto3" json:"paid,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *PayoutInfo) Reset() { *m = PayoutInfo{} }
func (m *PayoutInfo) String() string { return proto.CompactTextString(m) }
func (*PayoutInfo) ProtoMessage() {}
func (*PayoutInfo) Descriptor() ([]byte, []int) {
return fileDescriptor_9a45fd79b06f3a1b, []int{26}
}
func (m *PayoutInfo) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_PayoutInfo.Unmarshal(m, b)
}
func (m *PayoutInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_PayoutInfo.Marshal(b, m, deterministic)
}
func (m *PayoutInfo) XXX_Merge(src proto.Message) {
xxx_messageInfo_PayoutInfo.Merge(m, src)
}
func (m *PayoutInfo) XXX_Size() int {
return xxx_messageInfo_PayoutInfo.Size(m)
}
func (m *PayoutInfo) XXX_DiscardUnknown() {
xxx_messageInfo_PayoutInfo.DiscardUnknown(m)
}
var xxx_messageInfo_PayoutInfo proto.InternalMessageInfo
func (m *PayoutInfo) GetHeld() int64 {
if m != nil {
return m.Held
}
return 0
}
func (m *PayoutInfo) GetPaid() int64 {
if m != nil {
return m.Paid
}
return 0
}
func init() {
proto.RegisterType((*RequestHeader)(nil), "multinode.RequestHeader")
proto.RegisterType((*DiskSpaceRequest)(nil), "multinode.DiskSpaceRequest")
@ -1054,77 +1260,90 @@ func init() {
proto.RegisterType((*EstimatedPayoutSatelliteResponse)(nil), "multinode.EstimatedPayoutSatelliteResponse")
proto.RegisterType((*EstimatedPayoutTotalRequest)(nil), "multinode.EstimatedPayoutTotalRequest")
proto.RegisterType((*EstimatedPayoutTotalResponse)(nil), "multinode.EstimatedPayoutTotalResponse")
proto.RegisterType((*AllSatellitesSummaryRequest)(nil), "multinode.AllSatellitesSummaryRequest")
proto.RegisterType((*AllSatellitesSummaryResponse)(nil), "multinode.AllSatellitesSummaryResponse")
proto.RegisterType((*AllSatellitesPeriodSummaryRequest)(nil), "multinode.AllSatellitesPeriodSummaryRequest")
proto.RegisterType((*AllSatellitesPeriodSummaryResponse)(nil), "multinode.AllSatellitesPeriodSummaryResponse")
proto.RegisterType((*EarnedRequest)(nil), "multinode.EarnedRequest")
proto.RegisterType((*EarnedResponse)(nil), "multinode.EarnedResponse")
proto.RegisterType((*EarnedPerSatelliteRequest)(nil), "multinode.EarnedPerSatelliteRequest")
proto.RegisterType((*EarnedPerSatelliteResponse)(nil), "multinode.EarnedPerSatelliteResponse")
proto.RegisterType((*EarnedSatellite)(nil), "multinode.EarnedSatellite")
proto.RegisterType((*PayoutInfo)(nil), "multinode.PayoutInfo")
}
func init() { proto.RegisterFile("multinode.proto", fileDescriptor_9a45fd79b06f3a1b) }
var fileDescriptor_9a45fd79b06f3a1b = []byte{
// 992 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0x51, 0x73, 0xdb, 0x44,
0x10, 0x46, 0x49, 0x2c, 0xd7, 0x6b, 0x37, 0x8e, 0x8f, 0xcc, 0xa0, 0xa8, 0x4e, 0x9d, 0x51, 0x43,
0x13, 0x28, 0xd8, 0xe0, 0x3e, 0x31, 0x03, 0x33, 0xd4, 0x24, 0xa5, 0x19, 0x1c, 0x9a, 0xca, 0x81,
0x87, 0x32, 0x53, 0xcf, 0xc5, 0xba, 0x3a, 0xa2, 0xb2, 0x4e, 0xe8, 0x4e, 0x01, 0xff, 0x01, 0x86,
0x47, 0xfe, 0x11, 0xc3, 0x0b, 0xc3, 0x6f, 0xe0, 0xa1, 0xfc, 0x0c, 0x5e, 0x19, 0xdd, 0x9d, 0x64,
0xd9, 0x96, 0x9d, 0x8e, 0x33, 0xd3, 0x37, 0xdd, 0xee, 0xb7, 0xdf, 0xb7, 0xda, 0x5b, 0xed, 0x0a,
0xaa, 0xa3, 0xc8, 0xe3, 0xae, 0x4f, 0x1d, 0xd2, 0x0c, 0x42, 0xca, 0x29, 0x2a, 0xa5, 0x06, 0x13,
0x86, 0x74, 0x48, 0xa5, 0xd9, 0x6c, 0x0c, 0x29, 0x1d, 0x7a, 0xa4, 0x25, 0x4e, 0x17, 0xd1, 0xcb,
0x16, 0x77, 0x47, 0x84, 0x71, 0x3c, 0x0a, 0x24, 0xc0, 0x3a, 0x84, 0xdb, 0x36, 0xf9, 0x29, 0x22,
0x8c, 0x3f, 0x21, 0xd8, 0x21, 0x21, 0x7a, 0x0f, 0x8a, 0x38, 0x70, 0xfb, 0xaf, 0xc8, 0xd8, 0xd0,
0xf6, 0xb4, 0xc3, 0x8a, 0xad, 0xe3, 0xc0, 0xfd, 0x86, 0x8c, 0xad, 0x23, 0xd8, 0x3a, 0x72, 0xd9,
0xab, 0x5e, 0x80, 0x07, 0x44, 0x85, 0xa0, 0x4f, 0x40, 0xbf, 0x14, 0x61, 0x02, 0x5b, 0x6e, 0x1b,
0xcd, 0x49, 0x5e, 0x53, 0xb4, 0xb6, 0xc2, 0x59, 0x7f, 0x68, 0x50, 0xcb, 0xd0, 0xb0, 0x80, 0xfa,
0x8c, 0xa0, 0x3a, 0x94, 0xb0, 0xe7, 0xd1, 0x01, 0xe6, 0xc4, 0x11, 0x54, 0xeb, 0xf6, 0xc4, 0x80,
0x1a, 0x50, 0x8e, 0x18, 0x71, 0xfa, 0x81, 0x4b, 0x06, 0x84, 0x19, 0x6b, 0xc2, 0x0f, 0xb1, 0xe9,
0x4c, 0x58, 0xd0, 0x2e, 0x88, 0x53, 0x9f, 0x87, 0x98, 0x5d, 0x1a, 0xeb, 0x32, 0x3e, 0xb6, 0x9c,
0xc7, 0x06, 0x84, 0x60, 0xe3, 0x65, 0x48, 0x88, 0xb1, 0x21, 0x1c, 0xe2, 0x59, 0x28, 0x5e, 0x61,
0xd7, 0xc3, 0x17, 0x1e, 0x31, 0x0a, 0x4a, 0x31, 0x31, 0x20, 0x13, 0x6e, 0xd1, 0x2b, 0x12, 0xc6,
0x14, 0x86, 0x2e, 0x9c, 0xe9, 0xd9, 0x3a, 0x83, 0x7a, 0x07, 0xfb, 0xce, 0xcf, 0xae, 0xc3, 0x2f,
0x4f, 0xa9, 0xcf, 0x2f, 0x7b, 0xd1, 0x68, 0x84, 0xc3, 0xf1, 0xea, 0x35, 0x79, 0x08, 0xbb, 0x0b,
0x18, 0x55, 0x79, 0x10, 0x6c, 0x88, 0x54, 0x64, 0x65, 0xc4, 0xb3, 0xd5, 0x81, 0xcd, 0xef, 0x49,
0xc8, 0x5c, 0xea, 0xaf, 0x2e, 0xfc, 0x00, 0xaa, 0x29, 0x87, 0x92, 0x32, 0xa0, 0x78, 0x25, 0x4d,
0x82, 0xa5, 0x64, 0x27, 0x47, 0xeb, 0x31, 0xa0, 0x2e, 0x66, 0xfc, 0x2b, 0xea, 0x73, 0x3c, 0xe0,
0xab, 0x8b, 0xbe, 0x80, 0x77, 0xa7, 0x78, 0x94, 0xf0, 0xd7, 0x50, 0xf1, 0x30, 0xe3, 0xfd, 0x81,
0xb4, 0x2b, 0x3a, 0xb3, 0x29, 0x1b, 0xb8, 0x99, 0x34, 0x70, 0xf3, 0x3c, 0x69, 0xe0, 0xce, 0xad,
0xbf, 0x5f, 0x37, 0xde, 0xf9, 0xfd, 0xdf, 0x86, 0x66, 0x97, 0xbd, 0x09, 0xa1, 0xf5, 0x0b, 0xd4,
0x6c, 0x12, 0x44, 0x1c, 0xf3, 0x9b, 0xd4, 0x06, 0x7d, 0x0a, 0x15, 0x86, 0x39, 0xf1, 0x3c, 0x97,
0x93, 0xbe, 0xeb, 0x88, 0xae, 0xab, 0x74, 0x36, 0x63, 0xcd, 0x7f, 0x5e, 0x37, 0xf4, 0x6f, 0xa9,
0x43, 0x4e, 0x8e, 0xec, 0x72, 0x8a, 0x39, 0x71, 0xac, 0xff, 0x34, 0x40, 0x59, 0x69, 0xf5, 0x66,
0x9f, 0x83, 0x4e, 0x7d, 0xcf, 0xf5, 0x89, 0xd2, 0xde, 0x9f, 0xd2, 0x9e, 0x85, 0x37, 0x9f, 0x0a,
0xac, 0xad, 0x62, 0xd0, 0x67, 0x50, 0xc0, 0x91, 0xe3, 0x72, 0x91, 0x40, 0xb9, 0x7d, 0x6f, 0x79,
0xf0, 0xa3, 0x18, 0x6a, 0xcb, 0x08, 0xf3, 0x2e, 0xe8, 0x92, 0x0c, 0x6d, 0x43, 0x81, 0x0d, 0x68,
0x28, 0x33, 0xd0, 0x6c, 0x79, 0x30, 0x9f, 0x40, 0x41, 0xe0, 0xf3, 0xdd, 0xe8, 0x03, 0xd8, 0x62,
0x11, 0x0b, 0x88, 0x1f, 0x5f, 0x7f, 0x5f, 0x02, 0xd6, 0x04, 0xa0, 0x3a, 0xb1, 0xf7, 0x62, 0xb3,
0xd5, 0x05, 0xe3, 0x3c, 0x8c, 0x18, 0x27, 0x4e, 0x2f, 0xa9, 0x07, 0x5b, 0xbd, 0x43, 0xfe, 0xd2,
0x60, 0x27, 0x87, 0x4e, 0x95, 0xf3, 0x07, 0x40, 0x5c, 0x3a, 0xfb, 0x69, 0xf1, 0x99, 0xa1, 0xed,
0xad, 0x1f, 0x96, 0xdb, 0x1f, 0x65, 0xb8, 0x17, 0x32, 0x34, 0xe3, 0xbb, 0xfb, 0xce, 0xee, 0xda,
0x35, 0x3e, 0x0b, 0x31, 0xbb, 0x50, 0x54, 0x5e, 0x74, 0x00, 0xc5, 0x98, 0x27, 0xbe, 0x7b, 0x2d,
0xf7, 0xee, 0xf5, 0xd8, 0x7d, 0xe2, 0xc4, 0x9f, 0x0c, 0x76, 0x9c, 0x90, 0x30, 0x39, 0x9a, 0x4a,
0x76, 0x72, 0xb4, 0x7e, 0xd5, 0xa0, 0x71, 0xcc, 0xb8, 0x3b, 0x8a, 0xc7, 0xd8, 0x19, 0x1e, 0xd3,
0x88, 0xa7, 0x5a, 0x6f, 0xb5, 0x33, 0x9f, 0xc1, 0xde, 0xe2, 0x3c, 0x54, 0x5d, 0x3f, 0x06, 0x44,
0x12, 0x4c, 0x9f, 0xe0, 0xd0, 0x77, 0xfd, 0x21, 0x53, 0x23, 0xa7, 0x96, 0x7a, 0x8e, 0x95, 0xc3,
0x7a, 0x0a, 0x77, 0x66, 0x28, 0xcf, 0x29, 0xc7, 0xde, 0xea, 0xb7, 0x7e, 0x0a, 0xf5, 0x7c, 0xc2,
0xd5, 0xf2, 0x7b, 0x04, 0xb7, 0xe3, 0x67, 0xe2, 0xac, 0x9e, 0xd1, 0x7d, 0xd8, 0x4c, 0x28, 0x54,
0x0e, 0xdb, 0x50, 0xe0, 0x71, 0x52, 0x4a, 0x56, 0x1e, 0xac, 0x53, 0xd8, 0x91, 0xb8, 0x33, 0x12,
0xde, 0xfc, 0x7e, 0xad, 0x01, 0x98, 0x79, 0x74, 0x2a, 0x85, 0x63, 0xd8, 0x22, 0xc2, 0x3b, 0xe9,
0x7e, 0xd5, 0xfc, 0x66, 0x86, 0x59, 0x12, 0x4c, 0xa2, 0xab, 0x64, 0xda, 0x60, 0x3d, 0x87, 0xea,
0x0c, 0x26, 0xff, 0xe5, 0x56, 0xe8, 0xb6, 0xf6, 0x33, 0x28, 0xf6, 0x38, 0x0d, 0xf1, 0x90, 0xa0,
0xc7, 0x50, 0x4a, 0xb7, 0x3d, 0xba, 0x93, 0x49, 0x70, 0xf6, 0x57, 0xc2, 0xac, 0xe7, 0x3b, 0xe5,
0x5b, 0xb7, 0x7d, 0x28, 0xa5, 0x2b, 0x12, 0x61, 0xa8, 0x64, 0xd7, 0x24, 0x3a, 0xc8, 0x84, 0x2e,
0x5b, 0xcd, 0xe6, 0xe1, 0xf5, 0x40, 0xa5, 0xf7, 0xe7, 0x1a, 0x6c, 0xc4, 0xaf, 0x86, 0xbe, 0x84,
0xa2, 0x5a, 0x91, 0x68, 0x27, 0x13, 0x3d, 0xbd, 0x7a, 0x4d, 0x33, 0xcf, 0xa5, 0x2e, 0xac, 0x0b,
0xe5, 0xcc, 0xbe, 0x43, 0xbb, 0x19, 0xe8, 0xfc, 0x3e, 0x35, 0xef, 0x2e, 0x72, 0x2b, 0xb6, 0x13,
0x80, 0xc9, 0xd8, 0x47, 0xf5, 0x05, 0xdb, 0x40, 0x72, 0xed, 0x2e, 0xdd, 0x15, 0xe8, 0x05, 0xd4,
0xe6, 0x66, 0x24, 0xba, 0xb7, 0x7c, 0x82, 0x4a, 0xe2, 0xfd, 0x37, 0x19, 0xb3, 0xed, 0xdf, 0xd6,
0x41, 0x97, 0x1f, 0x32, 0xfa, 0x02, 0x74, 0xd9, 0x6d, 0xc8, 0x98, 0x6b, 0xd2, 0x84, 0x74, 0x27,
0xc7, 0xa3, 0x32, 0xc5, 0x80, 0xe6, 0xbf, 0x08, 0xb4, 0x3f, 0x17, 0x90, 0xf3, 0xfd, 0x99, 0xef,
0x5f, 0x83, 0x52, 0x12, 0x0c, 0x8c, 0x45, 0x13, 0x12, 0x7d, 0x98, 0xa5, 0x58, 0x3e, 0xce, 0xcd,
0x07, 0x6f, 0x84, 0x55, 0xa2, 0x43, 0xd8, 0xce, 0x1b, 0x79, 0xe8, 0xfe, 0x62, 0x92, 0xec, 0x90,
0x35, 0x0f, 0xae, 0xc5, 0x49, 0xa1, 0xce, 0xfe, 0x73, 0x8b, 0x71, 0x1a, 0xfe, 0xd8, 0x74, 0x69,
0x4b, 0x3c, 0xb4, 0x82, 0xd0, 0xbd, 0xc2, 0x9c, 0xb4, 0x52, 0x82, 0xe0, 0xe2, 0x42, 0x17, 0x3f,
0x59, 0x0f, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x99, 0x4e, 0x9a, 0xfe, 0x5d, 0x0c, 0x00, 0x00,
// 1120 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0x5f, 0x73, 0xdb, 0x44,
0x10, 0x47, 0x4d, 0x22, 0xd7, 0xeb, 0x34, 0x7f, 0x8e, 0x00, 0x8a, 0xea, 0xd4, 0x41, 0x0d, 0x4d,
0xa0, 0xad, 0x03, 0x2e, 0xc3, 0x0c, 0x33, 0x30, 0x43, 0x42, 0x52, 0x9a, 0x21, 0xa1, 0xa9, 0x1c,
0xfa, 0x50, 0x98, 0x7a, 0x2e, 0xd6, 0xc5, 0x16, 0x95, 0x75, 0x42, 0x77, 0x0a, 0xf8, 0x0b, 0xf0,
0xcc, 0x37, 0x62, 0x78, 0x61, 0xf8, 0x0c, 0x3c, 0x94, 0x2f, 0xc0, 0x3b, 0xaf, 0xcc, 0xfd, 0xb1,
0x2c, 0xdb, 0xb2, 0x93, 0xb1, 0x67, 0x78, 0xbb, 0xdb, 0xfd, 0xed, 0x6f, 0xf7, 0x76, 0xef, 0xf6,
0x16, 0x96, 0x3b, 0x49, 0xc0, 0xfd, 0x90, 0x7a, 0xa4, 0x1a, 0xc5, 0x94, 0x53, 0x54, 0x4c, 0x05,
0x36, 0xb4, 0x68, 0x8b, 0x2a, 0xb1, 0x5d, 0x69, 0x51, 0xda, 0x0a, 0xc8, 0xae, 0xdc, 0x9d, 0x27,
0x17, 0xbb, 0xdc, 0xef, 0x10, 0xc6, 0x71, 0x27, 0x52, 0x00, 0x67, 0x07, 0x6e, 0xb9, 0xe4, 0xc7,
0x84, 0x30, 0xfe, 0x84, 0x60, 0x8f, 0xc4, 0xe8, 0x1d, 0x28, 0xe0, 0xc8, 0x6f, 0xbc, 0x22, 0x5d,
0xcb, 0xd8, 0x34, 0x76, 0x16, 0x5d, 0x13, 0x47, 0xfe, 0xd7, 0xa4, 0xeb, 0x1c, 0xc0, 0xca, 0x81,
0xcf, 0x5e, 0xd5, 0x23, 0xdc, 0x24, 0xda, 0x04, 0x7d, 0x08, 0x66, 0x5b, 0x9a, 0x49, 0x6c, 0xa9,
0x66, 0x55, 0xfb, 0x71, 0x0d, 0xd0, 0xba, 0x1a, 0xe7, 0xfc, 0x66, 0xc0, 0x6a, 0x86, 0x86, 0x45,
0x34, 0x64, 0x04, 0x95, 0xa1, 0x88, 0x83, 0x80, 0x36, 0x31, 0x27, 0x9e, 0xa4, 0x9a, 0x73, 0xfb,
0x02, 0x54, 0x81, 0x52, 0xc2, 0x88, 0xd7, 0x88, 0x7c, 0xd2, 0x24, 0xcc, 0xba, 0x21, 0xf5, 0x20,
0x44, 0xa7, 0x52, 0x82, 0x36, 0x40, 0xee, 0x1a, 0x3c, 0xc6, 0xac, 0x6d, 0xcd, 0x29, 0x7b, 0x21,
0x39, 0x13, 0x02, 0x84, 0x60, 0xfe, 0x22, 0x26, 0xc4, 0x9a, 0x97, 0x0a, 0xb9, 0x96, 0x1e, 0x2f,
0xb1, 0x1f, 0xe0, 0xf3, 0x80, 0x58, 0x0b, 0xda, 0x63, 0x4f, 0x80, 0x6c, 0xb8, 0x49, 0x2f, 0x49,
0x2c, 0x28, 0x2c, 0x53, 0x2a, 0xd3, 0xbd, 0x73, 0x0a, 0xe5, 0x7d, 0x1c, 0x7a, 0x3f, 0xf9, 0x1e,
0x6f, 0x9f, 0xd0, 0x90, 0xb7, 0xeb, 0x49, 0xa7, 0x83, 0xe3, 0xee, 0xf4, 0x39, 0x79, 0x04, 0x1b,
0x63, 0x18, 0x75, 0x7a, 0x10, 0xcc, 0xcb, 0x50, 0x54, 0x66, 0xe4, 0xda, 0xd9, 0x87, 0xa5, 0xe7,
0x24, 0x66, 0x3e, 0x0d, 0xa7, 0x77, 0x7c, 0x1f, 0x96, 0x53, 0x0e, 0xed, 0xca, 0x82, 0xc2, 0xa5,
0x12, 0x49, 0x96, 0xa2, 0xdb, 0xdb, 0x3a, 0x8f, 0x01, 0x1d, 0x63, 0xc6, 0xbf, 0xa4, 0x21, 0xc7,
0x4d, 0x3e, 0xbd, 0xd3, 0x97, 0xf0, 0xe6, 0x00, 0x8f, 0x76, 0xfc, 0x15, 0x2c, 0x06, 0x98, 0xf1,
0x46, 0x53, 0xc9, 0x35, 0x9d, 0x5d, 0x55, 0x17, 0xb8, 0xda, 0xbb, 0xc0, 0xd5, 0xb3, 0xde, 0x05,
0xde, 0xbf, 0xf9, 0xe7, 0xeb, 0xca, 0x1b, 0xbf, 0xfe, 0x5d, 0x31, 0xdc, 0x52, 0xd0, 0x27, 0x74,
0x7e, 0x86, 0x55, 0x97, 0x44, 0x09, 0xc7, 0x7c, 0x96, 0xdc, 0xa0, 0x8f, 0x60, 0x91, 0x61, 0x4e,
0x82, 0xc0, 0xe7, 0xa4, 0xe1, 0x7b, 0xf2, 0xd6, 0x2d, 0xee, 0x2f, 0x09, 0x9f, 0x7f, 0xbd, 0xae,
0x98, 0xdf, 0x50, 0x8f, 0x1c, 0x1d, 0xb8, 0xa5, 0x14, 0x73, 0xe4, 0x39, 0xff, 0x1a, 0x80, 0xb2,
0xae, 0xf5, 0xc9, 0x3e, 0x03, 0x93, 0x86, 0x81, 0x1f, 0x12, 0xed, 0x7b, 0x6b, 0xc0, 0xf7, 0x30,
0xbc, 0xfa, 0x54, 0x62, 0x5d, 0x6d, 0x83, 0x3e, 0x85, 0x05, 0x9c, 0x78, 0x3e, 0x97, 0x01, 0x94,
0x6a, 0x77, 0x27, 0x1b, 0xef, 0x09, 0xa8, 0xab, 0x2c, 0xec, 0x3b, 0x60, 0x2a, 0x32, 0xb4, 0x06,
0x0b, 0xac, 0x49, 0x63, 0x15, 0x81, 0xe1, 0xaa, 0x8d, 0xfd, 0x04, 0x16, 0x24, 0x3e, 0x5f, 0x8d,
0xde, 0x87, 0x15, 0x96, 0xb0, 0x88, 0x84, 0xa2, 0xfc, 0x0d, 0x05, 0xb8, 0x21, 0x01, 0xcb, 0x7d,
0x79, 0x5d, 0x88, 0x9d, 0x63, 0xb0, 0xce, 0xe2, 0x84, 0x71, 0xe2, 0xd5, 0x7b, 0xf9, 0x60, 0xd3,
0xdf, 0x90, 0x3f, 0x0c, 0x58, 0xcf, 0xa1, 0xd3, 0xe9, 0xfc, 0x0e, 0x10, 0x57, 0xca, 0x46, 0x9a,
0x7c, 0x66, 0x19, 0x9b, 0x73, 0x3b, 0xa5, 0xda, 0x83, 0x0c, 0xf7, 0x58, 0x86, 0xaa, 0xa8, 0xdd,
0xb7, 0xee, 0xb1, 0xbb, 0xca, 0x87, 0x21, 0xf6, 0x31, 0x14, 0xb4, 0x16, 0x6d, 0x43, 0x41, 0xf0,
0x88, 0xda, 0x1b, 0xb9, 0xb5, 0x37, 0x85, 0xfa, 0xc8, 0x13, 0x4f, 0x06, 0x7b, 0x5e, 0x4c, 0x98,
0x6a, 0x4d, 0x45, 0xb7, 0xb7, 0x75, 0x7e, 0x31, 0xa0, 0x72, 0xc8, 0xb8, 0xdf, 0x11, 0x6d, 0xec,
0x14, 0x77, 0x69, 0xc2, 0x53, 0x5f, 0xff, 0xeb, 0xcd, 0x7c, 0x06, 0x9b, 0xe3, 0xe3, 0xd0, 0x79,
0x7d, 0x08, 0x88, 0xf4, 0x30, 0x0d, 0x82, 0xe3, 0xd0, 0x0f, 0x5b, 0x4c, 0xb7, 0x9c, 0xd5, 0x54,
0x73, 0xa8, 0x15, 0xce, 0x53, 0xb8, 0x3d, 0x44, 0x79, 0x46, 0x39, 0x0e, 0xa6, 0xaf, 0xfa, 0x09,
0x94, 0xf3, 0x09, 0xa7, 0x8e, 0x6f, 0x2f, 0x08, 0xfa, 0xa5, 0x9d, 0xb9, 0x4b, 0x3f, 0x87, 0x72,
0x3e, 0xa1, 0x8e, 0xef, 0x13, 0x28, 0x45, 0x32, 0xec, 0x86, 0x1f, 0x5e, 0x50, 0x4d, 0xfb, 0x56,
0x86, 0x56, 0x1d, 0xea, 0x28, 0xbc, 0xa0, 0x2e, 0x44, 0xe9, 0xda, 0xe9, 0xc0, 0xbb, 0x03, 0xbc,
0xa7, 0x24, 0xf6, 0xa9, 0x37, 0x6b, 0xb8, 0xe8, 0x6d, 0x30, 0x23, 0xc9, 0xa4, 0x2f, 0xa5, 0xde,
0x39, 0xdf, 0x83, 0x33, 0xc9, 0xdd, 0x8c, 0x87, 0xd9, 0x83, 0x5b, 0xa2, 0x02, 0xc4, 0x9b, 0x3e,
0xcf, 0xf7, 0x60, 0xa9, 0x47, 0xa1, 0x83, 0x59, 0x83, 0x05, 0x2e, 0xae, 0x82, 0x2e, 0xb6, 0xda,
0x38, 0x27, 0xb0, 0xae, 0x70, 0xa7, 0x24, 0x9e, 0xfd, 0x55, 0x39, 0x4d, 0xb0, 0xf3, 0xe8, 0x74,
0x08, 0x87, 0xb0, 0x42, 0xa4, 0xb6, 0xdf, 0x73, 0x74, 0xcb, 0xb1, 0x33, 0xcc, 0x8a, 0xa0, 0x6f,
0xbd, 0x4c, 0x06, 0x05, 0xce, 0x0b, 0x58, 0x1e, 0xc2, 0xe4, 0x1f, 0x6e, 0x9a, 0x37, 0xfe, 0x31,
0x40, 0xbf, 0x28, 0x62, 0x64, 0x68, 0x93, 0x20, 0x1d, 0x19, 0xc4, 0x5a, 0xc8, 0x22, 0xac, 0xc9,
0xe6, 0x5c, 0xb9, 0xae, 0x3d, 0x83, 0x42, 0x9d, 0xd3, 0x18, 0xb7, 0x08, 0x7a, 0x0c, 0xc5, 0x74,
0x32, 0x43, 0xb7, 0x33, 0xc7, 0x1a, 0x1e, 0xfb, 0xec, 0x72, 0xbe, 0x52, 0xe5, 0xaa, 0x16, 0x42,
0x31, 0x1d, 0x67, 0x10, 0x86, 0xc5, 0xec, 0x48, 0x83, 0xb6, 0x33, 0xa6, 0x93, 0xc6, 0x28, 0x7b,
0xe7, 0x6a, 0xa0, 0xf6, 0xf7, 0xfb, 0x0d, 0x98, 0x17, 0x09, 0x41, 0x5f, 0x40, 0x41, 0x8f, 0x33,
0x68, 0x3d, 0x63, 0x3d, 0x38, 0x26, 0xd9, 0x76, 0x9e, 0x4a, 0x97, 0xf9, 0x18, 0x4a, 0x99, 0xd9,
0x04, 0x6d, 0x64, 0xa0, 0xa3, 0xb3, 0x8f, 0x7d, 0x67, 0x9c, 0x5a, 0xb3, 0x1d, 0x01, 0xf4, 0xbf,
0x68, 0x54, 0x1e, 0xf3, 0x73, 0x2b, 0xae, 0x8d, 0x89, 0xff, 0x3a, 0x7a, 0x09, 0xab, 0x23, 0xff,
0x19, 0xba, 0x3b, 0xf9, 0xb7, 0x53, 0xc4, 0x5b, 0xd7, 0xf9, 0x12, 0x6b, 0xff, 0xcc, 0x83, 0xa9,
0x6e, 0x0f, 0x6a, 0xc1, 0x5a, 0x5e, 0x9f, 0x43, 0xf7, 0x32, 0x44, 0x13, 0x3a, 0xab, 0xbd, 0x7d,
0x25, 0x4e, 0x9f, 0xa9, 0x0b, 0xf6, 0xf8, 0x4e, 0x84, 0x1e, 0x8c, 0xa3, 0xc9, 0xeb, 0x8f, 0xf6,
0xc3, 0x6b, 0xa2, 0xb5, 0xeb, 0xcf, 0xc1, 0x54, 0xef, 0x10, 0x59, 0x23, 0xcf, 0xb7, 0x47, 0xb9,
0x9e, 0xa3, 0xd1, 0xe6, 0x18, 0xd0, 0x68, 0xaf, 0x40, 0x5b, 0x23, 0x06, 0x39, 0x9d, 0xc9, 0x7e,
0xef, 0x0a, 0x94, 0x76, 0xc1, 0xc0, 0x1a, 0xf7, 0x63, 0xa3, 0x0f, 0xb2, 0x14, 0x93, 0xc7, 0x0b,
0xfb, 0xfe, 0xb5, 0xb0, 0xda, 0x69, 0x0b, 0xd6, 0xf2, 0xbe, 0xe0, 0x81, 0xd2, 0x4f, 0xf8, 0xf4,
0x07, 0x4a, 0x3f, 0xe9, 0x2f, 0xdf, 0xdf, 0x7a, 0xe1, 0x30, 0x4e, 0xe3, 0x1f, 0xaa, 0x3e, 0xdd,
0x95, 0x8b, 0xdd, 0x28, 0xf6, 0x2f, 0x31, 0x27, 0xbb, 0x29, 0x41, 0x74, 0x7e, 0x6e, 0xca, 0xa1,
0xff, 0xd1, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xe2, 0x80, 0x59, 0xb0, 0xed, 0x0e, 0x00, 0x00,
}

View File

@ -97,6 +97,8 @@ message TrustedSatellitesResponse {
}
service Payout {
rpc AllSatellitesSummary(AllSatellitesSummaryRequest) returns (AllSatellitesSummaryResponse);
rpc AllSatellitesPeriodSummary(AllSatellitesPeriodSummaryRequest) returns (AllSatellitesPeriodSummaryResponse);
rpc Earned(EarnedRequest) returns (EarnedResponse);
rpc EarnedPerSatellite(EarnedPerSatelliteRequest) returns (EarnedPerSatelliteResponse);
rpc EstimatedPayoutSatellite(EstimatedPayoutSatelliteRequest) returns (EstimatedPayoutSatelliteResponse);
@ -117,6 +119,23 @@ message EstimatedPayoutTotalResponse {
int64 estimated_earnings = 1;
}
message AllSatellitesSummaryRequest {
RequestHeader header = 1;
}
message AllSatellitesSummaryResponse {
PayoutInfo payout_info = 1;
}
message AllSatellitesPeriodSummaryRequest {
RequestHeader header = 1;
string period = 2;
}
message AllSatellitesPeriodSummaryResponse {
PayoutInfo payout_info = 1;
}
message EarnedRequest {
RequestHeader header = 1;
}
@ -128,10 +147,17 @@ message EarnedResponse {
message EarnedPerSatelliteRequest {
RequestHeader header = 1;
}
message EarnedPerSatelliteResponse {
repeated EarnedSatellite earned_satellite = 1;
}
message EarnedSatellite {
int64 total = 1;
bytes satellite_id = 2 [(gogoproto.customtype) = "NodeID", (gogoproto.nullable) = false];
}
message PayoutInfo {
int64 held = 1;
int64 paid = 2;
}

View File

@ -387,6 +387,8 @@ func (x *drpcNode_TrustedSatellitesStream) SendAndClose(m *TrustedSatellitesResp
type DRPCPayoutClient interface {
DRPCConn() drpc.Conn
AllSatellitesSummary(ctx context.Context, in *AllSatellitesSummaryRequest) (*AllSatellitesSummaryResponse, error)
AllSatellitesPeriodSummary(ctx context.Context, in *AllSatellitesPeriodSummaryRequest) (*AllSatellitesPeriodSummaryResponse, error)
Earned(ctx context.Context, in *EarnedRequest) (*EarnedResponse, error)
EarnedPerSatellite(ctx context.Context, in *EarnedPerSatelliteRequest) (*EarnedPerSatelliteResponse, error)
EstimatedPayoutSatellite(ctx context.Context, in *EstimatedPayoutSatelliteRequest) (*EstimatedPayoutSatelliteResponse, error)
@ -403,6 +405,24 @@ func NewDRPCPayoutClient(cc drpc.Conn) DRPCPayoutClient {
func (c *drpcPayoutClient) DRPCConn() drpc.Conn { return c.cc }
func (c *drpcPayoutClient) AllSatellitesSummary(ctx context.Context, in *AllSatellitesSummaryRequest) (*AllSatellitesSummaryResponse, error) {
out := new(AllSatellitesSummaryResponse)
err := c.cc.Invoke(ctx, "/multinode.Payout/AllSatellitesSummary", drpcEncoding_File_multinode_proto{}, in, out)
if err != nil {
return nil, err
}
return out, nil
}
func (c *drpcPayoutClient) AllSatellitesPeriodSummary(ctx context.Context, in *AllSatellitesPeriodSummaryRequest) (*AllSatellitesPeriodSummaryResponse, error) {
out := new(AllSatellitesPeriodSummaryResponse)
err := c.cc.Invoke(ctx, "/multinode.Payout/AllSatellitesPeriodSummary", drpcEncoding_File_multinode_proto{}, in, out)
if err != nil {
return nil, err
}
return out, nil
}
func (c *drpcPayoutClient) Earned(ctx context.Context, in *EarnedRequest) (*EarnedResponse, error) {
out := new(EarnedResponse)
err := c.cc.Invoke(ctx, "/multinode.Payout/Earned", drpcEncoding_File_multinode_proto{}, in, out)
@ -440,6 +460,8 @@ func (c *drpcPayoutClient) EstimatedPayoutTotal(ctx context.Context, in *Estimat
}
type DRPCPayoutServer interface {
AllSatellitesSummary(context.Context, *AllSatellitesSummaryRequest) (*AllSatellitesSummaryResponse, error)
AllSatellitesPeriodSummary(context.Context, *AllSatellitesPeriodSummaryRequest) (*AllSatellitesPeriodSummaryResponse, error)
Earned(context.Context, *EarnedRequest) (*EarnedResponse, error)
EarnedPerSatellite(context.Context, *EarnedPerSatelliteRequest) (*EarnedPerSatelliteResponse, error)
EstimatedPayoutSatellite(context.Context, *EstimatedPayoutSatelliteRequest) (*EstimatedPayoutSatelliteResponse, error)
@ -448,6 +470,14 @@ type DRPCPayoutServer interface {
type DRPCPayoutUnimplementedServer struct{}
func (s *DRPCPayoutUnimplementedServer) AllSatellitesSummary(context.Context, *AllSatellitesSummaryRequest) (*AllSatellitesSummaryResponse, error) {
return nil, drpcerr.WithCode(errors.New("Unimplemented"), 12)
}
func (s *DRPCPayoutUnimplementedServer) AllSatellitesPeriodSummary(context.Context, *AllSatellitesPeriodSummaryRequest) (*AllSatellitesPeriodSummaryResponse, error) {
return nil, drpcerr.WithCode(errors.New("Unimplemented"), 12)
}
func (s *DRPCPayoutUnimplementedServer) Earned(context.Context, *EarnedRequest) (*EarnedResponse, error) {
return nil, drpcerr.WithCode(errors.New("Unimplemented"), 12)
}
@ -466,11 +496,29 @@ func (s *DRPCPayoutUnimplementedServer) EstimatedPayoutTotal(context.Context, *E
type DRPCPayoutDescription struct{}
func (DRPCPayoutDescription) NumMethods() int { return 4 }
func (DRPCPayoutDescription) NumMethods() int { return 6 }
func (DRPCPayoutDescription) Method(n int) (string, drpc.Encoding, drpc.Receiver, interface{}, bool) {
switch n {
case 0:
return "/multinode.Payout/AllSatellitesSummary", drpcEncoding_File_multinode_proto{},
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
return srv.(DRPCPayoutServer).
AllSatellitesSummary(
ctx,
in1.(*AllSatellitesSummaryRequest),
)
}, DRPCPayoutServer.AllSatellitesSummary, true
case 1:
return "/multinode.Payout/AllSatellitesPeriodSummary", drpcEncoding_File_multinode_proto{},
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
return srv.(DRPCPayoutServer).
AllSatellitesPeriodSummary(
ctx,
in1.(*AllSatellitesPeriodSummaryRequest),
)
}, DRPCPayoutServer.AllSatellitesPeriodSummary, true
case 2:
return "/multinode.Payout/Earned", drpcEncoding_File_multinode_proto{},
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
return srv.(DRPCPayoutServer).
@ -479,7 +527,7 @@ func (DRPCPayoutDescription) Method(n int) (string, drpc.Encoding, drpc.Receiver
in1.(*EarnedRequest),
)
}, DRPCPayoutServer.Earned, true
case 1:
case 3:
return "/multinode.Payout/EarnedPerSatellite", drpcEncoding_File_multinode_proto{},
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
return srv.(DRPCPayoutServer).
@ -488,7 +536,7 @@ func (DRPCPayoutDescription) Method(n int) (string, drpc.Encoding, drpc.Receiver
in1.(*EarnedPerSatelliteRequest),
)
}, DRPCPayoutServer.EarnedPerSatellite, true
case 2:
case 4:
return "/multinode.Payout/EstimatedPayoutSatellite", drpcEncoding_File_multinode_proto{},
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
return srv.(DRPCPayoutServer).
@ -497,7 +545,7 @@ func (DRPCPayoutDescription) Method(n int) (string, drpc.Encoding, drpc.Receiver
in1.(*EstimatedPayoutSatelliteRequest),
)
}, DRPCPayoutServer.EstimatedPayoutSatellite, true
case 3:
case 5:
return "/multinode.Payout/EstimatedPayoutTotal", drpcEncoding_File_multinode_proto{},
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
return srv.(DRPCPayoutServer).
@ -515,6 +563,38 @@ func DRPCRegisterPayout(mux drpc.Mux, impl DRPCPayoutServer) error {
return mux.Register(impl, DRPCPayoutDescription{})
}
type DRPCPayout_AllSatellitesSummaryStream interface {
drpc.Stream
SendAndClose(*AllSatellitesSummaryResponse) error
}
type drpcPayout_AllSatellitesSummaryStream struct {
drpc.Stream
}
func (x *drpcPayout_AllSatellitesSummaryStream) SendAndClose(m *AllSatellitesSummaryResponse) error {
if err := x.MsgSend(m, drpcEncoding_File_multinode_proto{}); err != nil {
return err
}
return x.CloseSend()
}
type DRPCPayout_AllSatellitesPeriodSummaryStream interface {
drpc.Stream
SendAndClose(*AllSatellitesPeriodSummaryResponse) error
}
type drpcPayout_AllSatellitesPeriodSummaryStream struct {
drpc.Stream
}
func (x *drpcPayout_AllSatellitesPeriodSummaryStream) SendAndClose(m *AllSatellitesPeriodSummaryResponse) error {
if err := x.MsgSend(m, drpcEncoding_File_multinode_proto{}); err != nil {
return err
}
return x.CloseSend()
}
type DRPCPayout_EarnedStream interface {
drpc.Stream
SendAndClose(*EarnedResponse) error

View File

@ -118,3 +118,57 @@ func (payout *PayoutEndpoint) EstimatedPayoutSatellite(ctx context.Context, req
return &multinodepb.EstimatedPayoutSatelliteResponse{EstimatedEarnings: estimated.CurrentMonthExpectations}, nil
}
// AllSatellitesSummary returns all satellites all time payout summary.
func (payout *PayoutEndpoint) AllSatellitesSummary(ctx context.Context, req *multinodepb.AllSatellitesSummaryRequest) (_ *multinodepb.AllSatellitesSummaryResponse, err error) {
defer mon.Task()(&ctx)(&err)
if err = authenticate(ctx, payout.apiKeys, req.GetHeader()); err != nil {
return nil, rpcstatus.Wrap(rpcstatus.Unauthenticated, err)
}
var totalPaid, totalHeld int64
satelliteIDs, err := payout.db.GetPayingSatellitesIDs(ctx)
if err != nil {
return &multinodepb.AllSatellitesSummaryResponse{}, rpcstatus.Wrap(rpcstatus.Internal, err)
}
for _, id := range satelliteIDs {
paid, held, err := payout.db.GetSatelliteSummary(ctx, id)
if err != nil {
return &multinodepb.AllSatellitesSummaryResponse{}, rpcstatus.Wrap(rpcstatus.Internal, err)
}
totalHeld += held
totalPaid += paid
}
return &multinodepb.AllSatellitesSummaryResponse{PayoutInfo: &multinodepb.PayoutInfo{Paid: totalPaid, Held: totalHeld}}, nil
}
// AllSatellitesPeriodSummary returns all satellites period payout summary.
func (payout *PayoutEndpoint) AllSatellitesPeriodSummary(ctx context.Context, req *multinodepb.AllSatellitesPeriodSummaryRequest) (_ *multinodepb.AllSatellitesPeriodSummaryResponse, err error) {
defer mon.Task()(&ctx)(&err)
if err = authenticate(ctx, payout.apiKeys, req.GetHeader()); err != nil {
return nil, rpcstatus.Wrap(rpcstatus.Unauthenticated, err)
}
var totalPaid, totalHeld int64
satelliteIDs, err := payout.db.GetPayingSatellitesIDs(ctx)
if err != nil {
return &multinodepb.AllSatellitesPeriodSummaryResponse{}, rpcstatus.Wrap(rpcstatus.Internal, err)
}
for _, id := range satelliteIDs {
paid, held, err := payout.db.GetSatellitePeriodSummary(ctx, id, req.Period)
if err != nil {
return &multinodepb.AllSatellitesPeriodSummaryResponse{}, rpcstatus.Wrap(rpcstatus.Internal, err)
}
totalHeld += held
totalPaid += paid
}
return &multinodepb.AllSatellitesPeriodSummaryResponse{PayoutInfo: &multinodepb.PayoutInfo{Held: totalHeld, Paid: totalPaid}}, nil
}

View File

@ -58,24 +58,48 @@ func TestEarnedPerSatellite(t *testing.T) {
estimatedPayoutsService := estimatedpayouts.NewService(planet.StorageNodes[0].DB.Bandwidth(), planet.StorageNodes[0].DB.Reputation(), planet.StorageNodes[0].DB.StorageUsage(), planet.StorageNodes[0].DB.Pricing(), planet.StorageNodes[0].DB.Satellites(), &trust.Pool{})
endpoint := multinode.NewPayoutEndpoint(log, service, estimatedPayoutsService, planet.StorageNodes[0].DB.Payout())
id := testrand.NodeID()
id2 := testrand.NodeID()
var amount int64 = 200
var amount2 int64 = 150
err := planet.StorageNodes[0].DB.Payout().StorePayStub(ctx, payouts.PayStub{
SatelliteID: testrand.NodeID(),
CompAtRest: amount,
SatelliteID: id,
Held: amount,
Paid: amount,
Period: "2020-10",
})
require.NoError(t, err)
err = planet.StorageNodes[0].DB.Payout().StorePayStub(ctx, payouts.PayStub{
SatelliteID: id2,
Held: amount2,
Paid: amount2,
Period: "2020-11",
})
require.NoError(t, err)
key, err := service.Issue(ctx)
require.NoError(t, err)
response, err := endpoint.EarnedPerSatellite(ctx, &multinodepb.EarnedPerSatelliteRequest{
response, err := endpoint.AllSatellitesPeriodSummary(ctx, &multinodepb.AllSatellitesPeriodSummaryRequest{
Header: &multinodepb.RequestHeader{
ApiKey: key.Secret[:],
}, Period: "2020-10",
})
require.NoError(t, err)
require.Equal(t, response.PayoutInfo.Paid, amount)
require.Equal(t, response.PayoutInfo.Held, amount)
response2, err := endpoint.AllSatellitesSummary(ctx, &multinodepb.AllSatellitesSummaryRequest{
Header: &multinodepb.RequestHeader{
ApiKey: key.Secret[:],
},
})
require.NoError(t, err)
require.Equal(t, response.EarnedSatellite[0].Total, amount)
require.Equal(t, response2.PayoutInfo.Paid, amount+amount2)
require.Equal(t, response2.PayoutInfo.Held, amount+amount2)
})
}

View File

@ -406,5 +406,52 @@ func TestPayouts(t *testing.T) {
require.Equal(t, int(satellite3Earned), 198)
require.NoError(t, err)
})
t.Run("Test GetSatelliteSummary", func(t *testing.T) {
id1 := storj.NodeID{1, 2, 3}
id2 := storj.NodeID{2, 3, 4}
err := payout.StorePayStub(ctx, payouts.PayStub{
Period: "2020-11",
SatelliteID: id1,
Paid: 11,
Held: 11,
})
require.NoError(t, err)
err = payout.StorePayStub(ctx, payouts.PayStub{
Period: "2020-10",
SatelliteID: id1,
Paid: 22,
Held: 22,
})
require.NoError(t, err)
err = payout.StorePayStub(ctx, payouts.PayStub{
Period: "2020-11",
SatelliteID: id2,
Paid: 33,
Held: 33,
})
require.NoError(t, err)
err = payout.StorePayStub(ctx, payouts.PayStub{
Period: "2020-10",
SatelliteID: id2,
Paid: 66,
Held: 66,
})
require.NoError(t, err)
paid, held, err := payout.GetSatellitePeriodSummary(ctx, id1, "2020-10")
require.NoError(t, err)
require.Equal(t, paid, int64(22))
require.Equal(t, held, int64(22))
paid2, held2, err := payout.GetSatelliteSummary(ctx, id2)
require.NoError(t, err)
require.Equal(t, paid2, int64(99))
require.Equal(t, held2, int64(99))
})
})
}

View File

@ -40,6 +40,10 @@ type DB interface {
GetEarnedAtSatellite(ctx context.Context, id storj.NodeID) (int64, error)
// GetPayingSatellitesIDs returns list of satellite ID's that ever paid to storagenode.
GetPayingSatellitesIDs(ctx context.Context) ([]storj.NodeID, error)
// GetSatelliteSummary returns satellite all time paid and held amounts.
GetSatelliteSummary(ctx context.Context, satelliteID storj.NodeID) (paid, held int64, err error)
// GetSatellitePeriodSummary returns satellite paid and held amounts for specific period.
GetSatellitePeriodSummary(ctx context.Context, satelliteID storj.NodeID, period string) (paid, held int64, err error)
}
// ErrNoPayStubForPeriod represents errors from the payouts database.

View File

@ -434,47 +434,133 @@ func (db *payoutDB) GetTotalEarned(ctx context.Context) (_ int64, err error) {
// GetEarnedAtSatellite returns total earned value for node from specific satellite.
func (db *payoutDB) GetEarnedAtSatellite(ctx context.Context, id storj.NodeID) (_ int64, err error) {
defer mon.Task()(&ctx)(&err)
query := `SELECT comp_at_rest, comp_get, comp_get_repair, comp_get_audit FROM paystubs WHERE satellite_id = ?`
rows, err := db.QueryContext(ctx, query, id)
if err != nil {
return 0, err
}
defer func() { err = errs.Combine(err, rows.Close()) }()
var totalEarned int64
for rows.Next() {
var compAtRest, compGet, compGetRepair, compGetAudit int64
err := rows.Scan(&compAtRest, &compGet, &compGetRepair, &compGetAudit)
if err != nil {
return 0, ErrPayout.Wrap(err)
}
totalEarned += compGetAudit + compGet + compGetRepair + compAtRest
}
if err = rows.Err(); err != nil {
return 0, ErrPayout.Wrap(err)
}
return totalEarned, nil
}
// GetPayingSatellitesIDs returns list of satellite ID's that ever paid to storagenode.
func (db *payoutDB) GetPayingSatellitesIDs(ctx context.Context) (_ []storj.NodeID, err error) {
defer mon.Task()(&ctx)(&err)
query := `SELECT DISTINCT (satellite_id) FROM paystubs`
rows, err := db.QueryContext(ctx, query)
if err != nil {
return nil, err
}
defer func() { err = errs.Combine(err, rows.Close()) }()
var satelliteIDs []storj.NodeID
for rows.Next() {
var satelliteID storj.NodeID
err := rows.Scan(&satelliteID)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return []storj.NodeID{}, nil
}
return nil, ErrPayout.Wrap(err)
}
satelliteIDs = append(satelliteIDs, satelliteID)
}
if err = rows.Err(); err != nil {
return nil, ErrPayout.Wrap(err)
}
return satelliteIDs, nil
}
// GetSatelliteSummary returns satellite all time paid and held amounts.
func (db *payoutDB) GetSatelliteSummary(ctx context.Context, satelliteID storj.NodeID) (_, _ int64, err error) {
defer mon.Task()(&ctx)(&err)
query := `SELECT paid, held FROM paystubs WHERE satellite_id = ?`
rows, err := db.QueryContext(ctx, query, satelliteID)
if err != nil {
return 0, 0, err
}
defer func() { err = errs.Combine(err, rows.Close()) }()
var paid, held int64
for rows.Next() {
var paidPeriod, heldPeriod int64
err := rows.Scan(&paidPeriod, &heldPeriod)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return 0, 0, nil
}
return 0, 0, ErrPayout.Wrap(err)
}
paid += paidPeriod
held += heldPeriod
}
if err = rows.Err(); err != nil {
return 0, 0, ErrPayout.Wrap(err)
}
return paid, held, nil
}
// GetSatellitePeriodSummary returns satellite paid and held amounts for specific period.
func (db *payoutDB) GetSatellitePeriodSummary(ctx context.Context, satelliteID storj.NodeID, period string) (_, _ int64, err error) {
defer mon.Task()(&ctx)(&err)
query := `SELECT paid, held FROM paystubs WHERE satellite_id = ? AND period = ?`
rows, err := db.QueryContext(ctx, query, satelliteID, period)
if err != nil {
return 0, 0, err
}
defer func() { err = errs.Combine(err, rows.Close()) }()
var paid, held int64
for rows.Next() {
err := rows.Scan(&paid, &held)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return 0, 0, nil
}
return 0, 0, ErrPayout.Wrap(err)
}
}
if err = rows.Err(); err != nil {
return 0, 0, ErrPayout.Wrap(err)
}
return paid, held, nil
}