Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

services/horizon/internal: Add fee_charged and max_fee to /fee_stats endpoint #1964

Merged
merged 14 commits into from
Nov 28, 2019
56 changes: 41 additions & 15 deletions protocols/horizon/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -624,25 +624,51 @@ type Metrics struct {
TxsubTotal LogTotalMetric `json:"txsub.total"`
}

type FeeDistribution struct {
Max int64 `json:"max,string"`
Min int64 `json:"min,string"`
Mode int64 `json:"mode,string"`
P10 int64 `json:"p10,string"`
P20 int64 `json:"p20,string"`
P30 int64 `json:"p30,string"`
P40 int64 `json:"p40,string"`
P50 int64 `json:"p50,string"`
P60 int64 `json:"p60,string"`
P70 int64 `json:"p70,string"`
P80 int64 `json:"p80,string"`
P90 int64 `json:"p90,string"`
P95 int64 `json:"p95,string"`
P99 int64 `json:"p99,string"`
}

// FeeStats represents a response of fees from horizon
// To do: implement fee suggestions if agreement is reached in https://github.com/stellar/go/issues/926
type FeeStats struct {
LastLedger int `json:"last_ledger,string"`
LastLedgerBaseFee int `json:"last_ledger_base_fee,string"`
// Action needed in release: horizon-v0.25.0
// Update type for LastLedger to uint32 and LastLedgerBaseFee to int64
LastLedger int `json:"last_ledger,string"`
LastLedgerBaseFee int `json:"last_ledger_base_fee,string"`

LedgerCapacityUsage float64 `json:"ledger_capacity_usage,string"`
MinAcceptedFee int `json:"min_accepted_fee,string"`
ModeAcceptedFee int `json:"mode_accepted_fee,string"`
P10AcceptedFee int `json:"p10_accepted_fee,string"`
P20AcceptedFee int `json:"p20_accepted_fee,string"`
P30AcceptedFee int `json:"p30_accepted_fee,string"`
P40AcceptedFee int `json:"p40_accepted_fee,string"`
P50AcceptedFee int `json:"p50_accepted_fee,string"`
P60AcceptedFee int `json:"p60_accepted_fee,string"`
P70AcceptedFee int `json:"p70_accepted_fee,string"`
P80AcceptedFee int `json:"p80_accepted_fee,string"`
P90AcceptedFee int `json:"p90_accepted_fee,string"`
P95AcceptedFee int `json:"p95_accepted_fee,string"`
P99AcceptedFee int `json:"p99_accepted_fee,string"`

// Action needed in release: horizon-v0.25.0
// Remove AcceptedFee fields
MinAcceptedFee int `json:"min_accepted_fee,string"`
ModeAcceptedFee int `json:"mode_accepted_fee,string"`
P10AcceptedFee int `json:"p10_accepted_fee,string"`
P20AcceptedFee int `json:"p20_accepted_fee,string"`
P30AcceptedFee int `json:"p30_accepted_fee,string"`
P40AcceptedFee int `json:"p40_accepted_fee,string"`
P50AcceptedFee int `json:"p50_accepted_fee,string"`
P60AcceptedFee int `json:"p60_accepted_fee,string"`
P70AcceptedFee int `json:"p70_accepted_fee,string"`
P80AcceptedFee int `json:"p80_accepted_fee,string"`
P90AcceptedFee int `json:"p90_accepted_fee,string"`
P95AcceptedFee int `json:"p95_accepted_fee,string"`
P99AcceptedFee int `json:"p99_accepted_fee,string"`

FeeCharged FeeDistribution `json:"fee_charged"`
MaxFee FeeDistribution `json:"max_fee"`
}

// TransactionsPage contains records of transaction information returned by Horizon
Expand Down
146 changes: 93 additions & 53 deletions services/horizon/internal/actions_operation_fee_stats.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package horizon

import (
"fmt"
"net/http"
"strconv"

hProtocol "github.com/stellar/go/protocols/horizon"
"github.com/stellar/go/services/horizon/internal/actions"
"github.com/stellar/go/services/horizon/internal/operationfeestats"
"github.com/stellar/go/support/render/hal"
"github.com/stellar/go/support/render/httpjson"
"github.com/stellar/go/support/render/problem"
)

Expand All @@ -16,26 +17,35 @@ import (

var _ actions.JSONer = (*FeeStatsAction)(nil)

// this struct is very similar to hProtocol.feeStats but drops the usage of int
// in favor of int64
type feeStats struct {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a temporary workaround while we update hProtocol.FeeStats

LastLedger uint32 `json:"last_ledger,string"`
LastLedgerBaseFee int64 `json:"last_ledger_base_fee,string"`
LedgerCapacityUsage float64 `json:"ledger_capacity_usage,string"`
MinAcceptedFee int64 `json:"min_accepted_fee,string"`
ModeAcceptedFee int64 `json:"mode_accepted_fee,string"`
P10AcceptedFee int64 `json:"p10_accepted_fee,string"`
P20AcceptedFee int64 `json:"p20_accepted_fee,string"`
P30AcceptedFee int64 `json:"p30_accepted_fee,string"`
P40AcceptedFee int64 `json:"p40_accepted_fee,string"`
P50AcceptedFee int64 `json:"p50_accepted_fee,string"`
P60AcceptedFee int64 `json:"p60_accepted_fee,string"`
P70AcceptedFee int64 `json:"p70_accepted_fee,string"`
P80AcceptedFee int64 `json:"p80_accepted_fee,string"`
P90AcceptedFee int64 `json:"p90_accepted_fee,string"`
P95AcceptedFee int64 `json:"p95_accepted_fee,string"`
P99AcceptedFee int64 `json:"p99_accepted_fee,string"`

FeeCharged hProtocol.FeeDistribution `json:"fee_charged"`
MaxFee hProtocol.FeeDistribution `json:"max_fee"`
}

// FeeStatsAction renders a few useful statistics that describe the
// current state of operation fees on the network.
type FeeStatsAction struct {
Action
FeeMin int64
FeeMode int64
FeeP10 int64
FeeP20 int64
FeeP30 int64
FeeP40 int64
FeeP50 int64
FeeP60 int64
FeeP70 int64
FeeP80 int64
FeeP90 int64
FeeP95 int64
FeeP99 int64
LedgerCapacityUsage string
LastBaseFee int64
LastLedger int64
feeStats feeStats
}

// JSON is a method for actions.JSON
Expand All @@ -47,7 +57,7 @@ func (action *FeeStatsAction) JSON() error {
Type: "endpoint_not_available",
Title: "Endpoint Not Available",
Status: http.StatusNotImplemented,
Detail: "/operation_fee_stats is unavailable when Horizon is not ingesting failed " +
Detail: "/fee_stats is unavailable when Horizon is not ingesting failed " +
"transactions. Set `INGEST_FAILED_TRANSACTIONS=true` to start ingesting them.",
}
problem.Render(action.R.Context(), action.W, p)
Expand All @@ -57,45 +67,75 @@ func (action *FeeStatsAction) JSON() error {
action.Do(
action.loadRecords,
func() {
hal.Render(action.W, map[string]string{
"min_accepted_fee": fmt.Sprint(action.FeeMin),
"mode_accepted_fee": fmt.Sprint(action.FeeMode),
"p10_accepted_fee": fmt.Sprint(action.FeeP10),
"p20_accepted_fee": fmt.Sprint(action.FeeP20),
"p30_accepted_fee": fmt.Sprint(action.FeeP30),
"p40_accepted_fee": fmt.Sprint(action.FeeP40),
"p50_accepted_fee": fmt.Sprint(action.FeeP50),
"p60_accepted_fee": fmt.Sprint(action.FeeP60),
"p70_accepted_fee": fmt.Sprint(action.FeeP70),
"p80_accepted_fee": fmt.Sprint(action.FeeP80),
"p90_accepted_fee": fmt.Sprint(action.FeeP90),
"p95_accepted_fee": fmt.Sprint(action.FeeP95),
"p99_accepted_fee": fmt.Sprint(action.FeeP99),
"ledger_capacity_usage": action.LedgerCapacityUsage,
"last_ledger_base_fee": fmt.Sprint(action.LastBaseFee),
"last_ledger": fmt.Sprint(action.LastLedger),
})
httpjson.Render(
action.W,
action.feeStats,
httpjson.HALJSON,
)
},
)
return action.Err
}

func (action *FeeStatsAction) loadRecords() {
cur := operationfeestats.CurrentState()
action.FeeMin = cur.FeeMin
action.FeeMode = cur.FeeMode
action.LastBaseFee = cur.LastBaseFee
action.LastLedger = cur.LastLedger
action.LedgerCapacityUsage = cur.LedgerCapacityUsage
action.FeeP10 = cur.FeeP10
action.FeeP20 = cur.FeeP20
action.FeeP30 = cur.FeeP30
action.FeeP40 = cur.FeeP40
action.FeeP50 = cur.FeeP50
action.FeeP60 = cur.FeeP60
action.FeeP70 = cur.FeeP70
action.FeeP80 = cur.FeeP80
action.FeeP90 = cur.FeeP90
action.FeeP95 = cur.FeeP95
action.FeeP99 = cur.FeeP99
action.feeStats.LastLedgerBaseFee = cur.LastBaseFee
action.feeStats.LastLedger = cur.LastLedger

ledgerCapacityUsage, err := strconv.ParseFloat(cur.LedgerCapacityUsage, 64)
if err != nil {
action.Err = err
return
}

action.feeStats.LedgerCapacityUsage = ledgerCapacityUsage

// FeeCharged
action.feeStats.FeeCharged.Max = cur.FeeChargedMax
action.feeStats.FeeCharged.Min = cur.FeeChargedMin
action.feeStats.FeeCharged.Mode = cur.FeeChargedMode
action.feeStats.FeeCharged.P10 = cur.FeeChargedP10
action.feeStats.FeeCharged.P20 = cur.FeeChargedP20
action.feeStats.FeeCharged.P30 = cur.FeeChargedP30
action.feeStats.FeeCharged.P40 = cur.FeeChargedP40
action.feeStats.FeeCharged.P50 = cur.FeeChargedP50
action.feeStats.FeeCharged.P60 = cur.FeeChargedP60
action.feeStats.FeeCharged.P70 = cur.FeeChargedP70
action.feeStats.FeeCharged.P80 = cur.FeeChargedP80
action.feeStats.FeeCharged.P90 = cur.FeeChargedP90
action.feeStats.FeeCharged.P95 = cur.FeeChargedP95
action.feeStats.FeeCharged.P99 = cur.FeeChargedP99

// MaxFee
action.feeStats.MaxFee.Max = cur.MaxFeeMax
action.feeStats.MaxFee.Min = cur.MaxFeeMin
action.feeStats.MaxFee.Mode = cur.MaxFeeMode
action.feeStats.MaxFee.P10 = cur.MaxFeeP10
action.feeStats.MaxFee.P20 = cur.MaxFeeP20
action.feeStats.MaxFee.P30 = cur.MaxFeeP30
action.feeStats.MaxFee.P40 = cur.MaxFeeP40
action.feeStats.MaxFee.P50 = cur.MaxFeeP50
action.feeStats.MaxFee.P60 = cur.MaxFeeP60
action.feeStats.MaxFee.P70 = cur.MaxFeeP70
action.feeStats.MaxFee.P80 = cur.MaxFeeP80
action.feeStats.MaxFee.P90 = cur.MaxFeeP90
action.feeStats.MaxFee.P95 = cur.MaxFeeP95
action.feeStats.MaxFee.P99 = cur.MaxFeeP99

// AcceptedFee is an alias for MaxFee
// Action needed in release: horizon-v0.25.0
// Remove AcceptedFee fields
action.feeStats.MinAcceptedFee = action.feeStats.MaxFee.Min
action.feeStats.ModeAcceptedFee = action.feeStats.MaxFee.Mode
action.feeStats.P10AcceptedFee = action.feeStats.MaxFee.P10
action.feeStats.P20AcceptedFee = action.feeStats.MaxFee.P20
action.feeStats.P30AcceptedFee = action.feeStats.MaxFee.P30
action.feeStats.P40AcceptedFee = action.feeStats.MaxFee.P40
action.feeStats.P50AcceptedFee = action.feeStats.MaxFee.P50
action.feeStats.P60AcceptedFee = action.feeStats.MaxFee.P60
action.feeStats.P70AcceptedFee = action.feeStats.MaxFee.P70
action.feeStats.P80AcceptedFee = action.feeStats.MaxFee.P80
action.feeStats.P90AcceptedFee = action.feeStats.MaxFee.P90
action.feeStats.P95AcceptedFee = action.feeStats.MaxFee.P95
action.feeStats.P99AcceptedFee = action.feeStats.MaxFee.P99
}
Loading