• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lightningnetwork / lnd / 15850020226

24 Jun 2025 12:09PM UTC coverage: 68.214% (+0.04%) from 68.172%
15850020226

push

github

web-flow
Merge pull request #9984 from starius/lntest-feeservice-mutex

lntest: do not do IO under mutex in fee_service

0 of 1 new or added line in 1 file covered. (0.0%)

334 existing lines in 31 files now uncovered.

134815 of 197636 relevant lines covered (68.21%)

22173.83 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/lntest/fee_service.go
1
package lntest
2

3
import (
4
        "context"
5
        "encoding/json"
6
        "fmt"
7
        "io"
8
        "net/http"
9
        "sync"
10
        "testing"
11

12
        "github.com/lightningnetwork/lnd"
13
        "github.com/lightningnetwork/lnd/lntest/port"
14
        "github.com/lightningnetwork/lnd/lnwallet/chainfee"
15
        "github.com/stretchr/testify/require"
16
)
17

18
// WebFeeService defines an interface that's used to provide fee estimation
19
// service used in the integration tests. It must provide an URL so that a lnd
20
// node can be started with the flag `--fee.url` and uses the customized fee
21
// estimator.
22
type WebFeeService interface {
23
        // Start starts the service.
24
        Start() error
25

26
        // Stop stops the service.
27
        Stop() error
28

29
        // URL returns the service's endpoint.
30
        URL() string
31

32
        // SetFeeRate sets the estimated fee rate for a given confirmation
33
        // target.
34
        SetFeeRate(feeRate chainfee.SatPerKWeight, conf uint32)
35

36
        // SetMinRelayFeerate sets a min relay feerate.
37
        SetMinRelayFeerate(fee chainfee.SatPerKVByte)
38

39
        // Reset resets the fee rate map to the default value.
40
        Reset()
41
}
42

43
const (
44
        // feeServiceTarget is the confirmation target for which a fee estimate
45
        // is returned. Requests for higher confirmation targets will fall back
46
        // to this.
47
        feeServiceTarget = 1
48

49
        // DefaultFeeRateSatPerKw specifies the default fee rate used in the
50
        // tests.
51
        DefaultFeeRateSatPerKw = 12500
52
)
53

54
// FeeService runs a web service that provides fee estimation information.
55
type FeeService struct {
56
        *testing.T
57

58
        feeRateMap      map[uint32]uint32
59
        minRelayFeerate chainfee.SatPerKVByte
60
        url             string
61

62
        srv  *http.Server
63
        wg   sync.WaitGroup
64
        lock sync.Mutex
65
}
66

67
// Compile-time check for the WebFeeService interface.
68
var _ WebFeeService = (*FeeService)(nil)
69

70
// NewFeeService spins up a go-routine to serve fee estimates.
71
func NewFeeService(t *testing.T) *FeeService {
×
72
        t.Helper()
×
73

×
74
        port := port.NextAvailablePort()
×
75
        f := FeeService{
×
76
                T: t,
×
77
                url: fmt.Sprintf(
×
78
                        "http://localhost:%v/fee-estimates.json", port,
×
79
                ),
×
80
        }
×
81

×
82
        // Initialize default fee estimate.
×
83
        f.feeRateMap = map[uint32]uint32{
×
84
                feeServiceTarget: DefaultFeeRateSatPerKw,
×
85
        }
×
86
        f.minRelayFeerate = chainfee.FeePerKwFloor.FeePerKVByte()
×
87

×
88
        listenAddr := fmt.Sprintf(":%v", port)
×
89
        mux := http.NewServeMux()
×
90
        mux.HandleFunc("/fee-estimates.json", f.handleRequest)
×
91

×
92
        f.srv = &http.Server{
×
93
                Addr:              listenAddr,
×
94
                Handler:           mux,
×
95
                ReadHeaderTimeout: lnd.DefaultHTTPHeaderTimeout,
×
96
        }
×
97

×
98
        return &f
×
99
}
×
100

101
// Start starts the web server.
102
func (f *FeeService) Start() error {
×
103
        f.wg.Add(1)
×
104
        go func() {
×
105
                defer f.wg.Done()
×
106

×
107
                if err := f.srv.ListenAndServe(); err != http.ErrServerClosed {
×
108
                        require.NoErrorf(f, err, "cannot start fee api")
×
109
                }
×
110
        }()
111

112
        return nil
×
113
}
114

115
// handleRequest handles a client request for fee estimates.
116
func (f *FeeService) handleRequest(w http.ResponseWriter, _ *http.Request) {
×
117
        f.lock.Lock()
×
118
        bytes, err := json.Marshal(
×
119
                chainfee.WebAPIResponse{
×
120
                        FeeByBlockTarget: f.feeRateMap,
×
121
                        MinRelayFeerate:  f.minRelayFeerate,
×
122
                },
×
123
        )
×
NEW
124
        f.lock.Unlock()
×
125
        require.NoErrorf(f, err, "cannot serialize estimates")
×
126

×
127
        _, err = io.WriteString(w, string(bytes))
×
128
        require.NoError(f, err, "cannot send estimates")
×
129
}
×
130

131
// Stop stops the web server.
132
func (f *FeeService) Stop() error {
×
133
        err := f.srv.Shutdown(context.Background())
×
134
        require.NoError(f, err, "cannot stop fee api")
×
135

×
136
        f.wg.Wait()
×
137

×
138
        return nil
×
139
}
×
140

141
// SetFeeRate sets a fee for the given confirmation target.
142
func (f *FeeService) SetFeeRate(fee chainfee.SatPerKWeight, conf uint32) {
×
143
        f.lock.Lock()
×
144
        defer f.lock.Unlock()
×
145

×
146
        f.feeRateMap[conf] = uint32(fee.FeePerKVByte())
×
147
}
×
148

149
// SetMinRelayFeerate sets a min relay feerate.
150
func (f *FeeService) SetMinRelayFeerate(fee chainfee.SatPerKVByte) {
×
151
        f.lock.Lock()
×
152
        defer f.lock.Unlock()
×
153

×
154
        f.minRelayFeerate = fee
×
155
}
×
156

157
// Reset resets the fee rate map to the default value.
158
func (f *FeeService) Reset() {
×
159
        f.lock.Lock()
×
160
        f.feeRateMap = make(map[uint32]uint32)
×
161
        f.minRelayFeerate = chainfee.FeePerKwFloor.FeePerKVByte()
×
162
        f.lock.Unlock()
×
163

×
164
        // Initialize default fee estimate.
×
165
        f.SetFeeRate(DefaultFeeRateSatPerKw, 1)
×
166
}
×
167

168
// URL returns the service endpoint.
169
func (f *FeeService) URL() string {
×
170
        return f.url
×
171
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc