This repository has been archived by the owner on May 16, 2019. It is now read-only.
forked from cjepson/dcrticketbuyer
-
Notifications
You must be signed in to change notification settings - Fork 7
/
feeest.go
131 lines (111 loc) · 3.49 KB
/
feeest.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Copyright (c) 2016 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package main
import (
"fmt"
"math"
"sort"
"github.com/decred/dcrutil"
)
const (
// windowsToConsider is the number of windows to consider
// when there is not enough block information to determine
// what the best fee should be.
windowsToConsider = 20
)
// diffPeriodFee defines some statistics about a difficulty fee period
// compared to the current difficulty period.
type diffPeriodFee struct {
difficulty float64
difference float64 // Difference from current difficulty
fee float64
}
// diffPeriodFees is slice type definition used to satisfy the sorting
// interface.
type diffPeriodFees []*diffPeriodFee
func (p diffPeriodFees) Len() int { return len(p) }
func (p diffPeriodFees) Less(i, j int) bool {
return p[i].difference < p[j].difference
}
func (p diffPeriodFees) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
// findClosestFeeWindows is used when there is not enough block information
// from recent blocks to figure out what to set the user's ticket fees to.
// Instead, it uses data from the last windowsToConsider many windows and
// takes an average fee from the closest one.
func (t *ticketPurchaser) findClosestFeeWindows(difficulty float64,
useMedian bool) (float64, error) {
wtcUint32 := uint32(windowsToConsider)
info, err := t.dcrdChainSvr.TicketFeeInfo(&zeroUint32, &wtcUint32)
if err != nil {
return 0.0, err
}
if len(info.FeeInfoWindows) == 0 {
return 0.0, fmt.Errorf("not enough windows to find mean fee " +
"available")
}
// Fetch all the mean fees and window difficulties. Calculate
// the difference from the current window and sort, then use
// the mean fee from the period that has the closest difficulty.
var sortable diffPeriodFees
for i := range info.FeeInfoWindows {
// Skip the first window if it's not full.
span := info.FeeInfoWindows[i].EndHeight -
info.FeeInfoWindows[i].StartHeight
if i == 0 && int64(span) < activeNet.StakeDiffWindowSize {
continue
}
startHeight := int64(info.FeeInfoWindows[i].StartHeight)
blH, err := t.dcrdChainSvr.GetBlockHash(startHeight)
if err != nil {
return 0.0, err
}
bl, err := t.dcrdChainSvr.GetBlock(blH)
if err != nil {
return 0.0, err
}
windowDiffAmt := dcrutil.Amount(bl.MsgBlock().Header.SBits)
windowDiff := windowDiffAmt.ToCoin()
fee := float64(0.0)
if !useMedian {
fee = info.FeeInfoWindows[i].Mean
} else {
fee = info.FeeInfoWindows[i].Median
}
// Skip all windows for which fee information does not exist
// because tickets were not purchased.
if fee == 0.0 {
continue
}
dpf := &diffPeriodFee{
difficulty: windowDiff,
difference: math.Abs(windowDiff - difficulty),
fee: fee,
}
sortable = append(sortable, dpf)
}
sort.Sort(sortable)
// No data available, prevent a panic.
if len(sortable) == 0 {
return 0, nil
}
return sortable[0].fee, nil
}
// findMeanTicketFeeBlocks finds the mean of the mean of fees from BlocksToAvg
// many blocks using the ticketfeeinfo RPC API.
func (t *ticketPurchaser) findTicketFeeBlocks(useMedian bool) (float64, error) {
btaUint32 := uint32(t.cfg.BlocksToAvg)
info, err := t.dcrdChainSvr.TicketFeeInfo(&btaUint32, nil)
if err != nil {
return 0.0, err
}
sum := 0.0
for i := range info.FeeInfoBlocks {
if !useMedian {
sum += info.FeeInfoBlocks[i].Mean
} else {
sum += info.FeeInfoBlocks[i].Median
}
}
return sum / float64(t.cfg.BlocksToAvg), nil
}