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

lightningnetwork / lnd / 13536249039

26 Feb 2025 03:42AM UTC coverage: 57.462% (-1.4%) from 58.835%
13536249039

Pull #8453

github

Roasbeef
peer: update chooseDeliveryScript to gen script if needed

In this commit, we update `chooseDeliveryScript` to generate a new
script if needed. This allows us to fold in a few other lines that
always followed this function into this expanded function.

The tests have been updated accordingly.
Pull Request #8453: [4/4] - multi: integrate new rbf coop close FSM into the existing peer flow

275 of 1318 new or added lines in 22 files covered. (20.86%)

19521 existing lines in 257 files now uncovered.

103858 of 180741 relevant lines covered (57.46%)

24750.23 hits per line

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

0.0
/watchtower/standalone.go
1
package watchtower
2

3
import (
4
        "net"
5
        "sync/atomic"
6
        "time"
7

8
        "github.com/btcsuite/btcd/btcec/v2"
9
        "github.com/lightningnetwork/lnd/brontide"
10
        "github.com/lightningnetwork/lnd/lnencrypt"
11
        "github.com/lightningnetwork/lnd/tor"
12
        "github.com/lightningnetwork/lnd/watchtower/lookout"
13
        "github.com/lightningnetwork/lnd/watchtower/wtserver"
14
)
15

16
// Standalone encapsulates the server-side functionality required by watchtower
17
// clients. A Standalone couples the two primary subsystems such that, as a
18
// unit, this instance can negotiate sessions with clients, accept state updates
19
// for active sessions, monitor the chain for breaches matching known breach
20
// hints, publish reconstructed justice transactions on behalf of tower clients.
21
type Standalone struct {
22
        started uint32 // to be used atomically
23
        stopped uint32 // to be used atomically
24

25
        cfg *Config
26

27
        // listeners is a reference to the wtserver's listeners.
28
        listeners []net.Listener
29

30
        // server is the client endpoint, used for negotiating sessions and
31
        // uploading state updates.
32
        server wtserver.Interface
33

34
        // lookout is a service that monitors the chain and inspects the
35
        // transactions found in new blocks against the state updates received
36
        // by the server.
37
        lookout lookout.Service
38
}
39

40
// New validates the passed Config and returns a fresh Standalone instance if
41
// the tower's subsystems could be properly initialized.
UNCOV
42
func New(cfg *Config) (*Standalone, error) {
×
UNCOV
43
        // The tower must have listening address in order to accept new updates
×
UNCOV
44
        // from clients.
×
UNCOV
45
        if len(cfg.ListenAddrs) == 0 {
×
46
                return nil, ErrNoListeners
×
47
        }
×
48

49
        // Assign the default read timeout if none is provided.
UNCOV
50
        if cfg.ReadTimeout == 0 {
×
51
                cfg.ReadTimeout = DefaultReadTimeout
×
52
        }
×
53

54
        // Assign the default write timeout if none is provided.
UNCOV
55
        if cfg.WriteTimeout == 0 {
×
56
                cfg.WriteTimeout = DefaultWriteTimeout
×
57
        }
×
58

UNCOV
59
        punisher := lookout.NewBreachPunisher(&lookout.PunisherConfig{
×
UNCOV
60
                PublishTx: cfg.PublishTx,
×
UNCOV
61
        })
×
UNCOV
62

×
UNCOV
63
        // Initialize the lookout service with its required resources.
×
UNCOV
64
        lookout := lookout.New(&lookout.Config{
×
UNCOV
65
                BlockFetcher:   cfg.BlockFetcher,
×
UNCOV
66
                DB:             cfg.DB,
×
UNCOV
67
                EpochRegistrar: cfg.EpochRegistrar,
×
UNCOV
68
                Punisher:       punisher,
×
UNCOV
69
                MinBackoff:     time.Second,
×
UNCOV
70
                MaxBackoff:     time.Minute,
×
UNCOV
71
                MaxNumRetries:  5,
×
UNCOV
72
        })
×
UNCOV
73

×
UNCOV
74
        // Create a brontide listener on each of the provided listening
×
UNCOV
75
        // addresses. Client should be able to connect to any of open ports to
×
UNCOV
76
        // communicate with this Standalone instance.
×
UNCOV
77
        listeners := make([]net.Listener, 0, len(cfg.ListenAddrs))
×
UNCOV
78
        for _, listenAddr := range cfg.ListenAddrs {
×
UNCOV
79
                listener, err := brontide.NewListener(
×
UNCOV
80
                        cfg.NodeKeyECDH, listenAddr.String(),
×
UNCOV
81
                )
×
UNCOV
82
                if err != nil {
×
83
                        return nil, err
×
84
                }
×
85

UNCOV
86
                listeners = append(listeners, listener)
×
87
        }
88

89
        // Initialize the server with its required resources.
UNCOV
90
        server, err := wtserver.New(&wtserver.Config{
×
UNCOV
91
                ChainHash:     cfg.ChainHash,
×
UNCOV
92
                DB:            cfg.DB,
×
UNCOV
93
                NodeKeyECDH:   cfg.NodeKeyECDH,
×
UNCOV
94
                Listeners:     listeners,
×
UNCOV
95
                ReadTimeout:   cfg.ReadTimeout,
×
UNCOV
96
                WriteTimeout:  cfg.WriteTimeout,
×
UNCOV
97
                NewAddress:    cfg.NewAddress,
×
UNCOV
98
                DisableReward: true,
×
UNCOV
99
        })
×
UNCOV
100
        if err != nil {
×
101
                return nil, err
×
102
        }
×
103

UNCOV
104
        return &Standalone{
×
UNCOV
105
                cfg:       cfg,
×
UNCOV
106
                listeners: listeners,
×
UNCOV
107
                server:    server,
×
UNCOV
108
                lookout:   lookout,
×
UNCOV
109
        }, nil
×
110
}
111

112
// Start idempotently starts the Standalone, an error is returned if the
113
// subsystems could not be initialized.
UNCOV
114
func (w *Standalone) Start() error {
×
UNCOV
115
        if !atomic.CompareAndSwapUint32(&w.started, 0, 1) {
×
116
                return nil
×
117
        }
×
118

UNCOV
119
        log.Infof("Starting watchtower")
×
UNCOV
120

×
UNCOV
121
        // If a tor controller exists in the config, then automatically create a
×
UNCOV
122
        // hidden service for the watchtower to accept inbound connections from.
×
UNCOV
123
        if w.cfg.TorController != nil {
×
124
                log.Infof("Creating watchtower hidden service")
×
125
                if err := w.createNewHiddenService(); err != nil {
×
126
                        return err
×
127
                }
×
128
        }
129

UNCOV
130
        if err := w.lookout.Start(); err != nil {
×
131
                return err
×
132
        }
×
UNCOV
133
        if err := w.server.Start(); err != nil {
×
134
                w.lookout.Stop()
×
135
                return err
×
136
        }
×
137

UNCOV
138
        log.Infof("Watchtower started successfully")
×
UNCOV
139

×
UNCOV
140
        return nil
×
141
}
142

143
// Stop idempotently stops the Standalone and blocks until the subsystems have
144
// completed their shutdown.
UNCOV
145
func (w *Standalone) Stop() error {
×
UNCOV
146
        if !atomic.CompareAndSwapUint32(&w.stopped, 0, 1) {
×
147
                return nil
×
148
        }
×
149

UNCOV
150
        log.Infof("Stopping watchtower")
×
UNCOV
151

×
UNCOV
152
        w.server.Stop()
×
UNCOV
153
        w.lookout.Stop()
×
UNCOV
154

×
UNCOV
155
        log.Infof("Watchtower stopped successfully")
×
UNCOV
156

×
UNCOV
157
        return nil
×
158
}
159

160
// createNewHiddenService automatically sets up a v2 or v3 onion service in
161
// order to listen for inbound connections over Tor.
162
func (w *Standalone) createNewHiddenService() error {
×
163
        // Get all the ports the watchtower is listening on. These will be used to
×
164
        // map the hidden service's virtual port.
×
165
        listenPorts := make([]int, 0, len(w.listeners))
×
166
        for _, listener := range w.listeners {
×
167
                port := listener.Addr().(*net.TCPAddr).Port
×
168
                listenPorts = append(listenPorts, port)
×
169
        }
×
170

171
        encrypter, err := lnencrypt.KeyRingEncrypter(w.cfg.KeyRing)
×
172
        if err != nil {
×
173
                return err
×
174
        }
×
175

176
        // Once we've created the port mapping, we can automatically create the
177
        // hidden service. The service's private key will be saved on disk in order
178
        // to persistently have access to this hidden service across restarts.
179
        onionCfg := tor.AddOnionConfig{
×
180
                VirtualPort: DefaultPeerPort,
×
181
                TargetPorts: listenPorts,
×
182
                Store: tor.NewOnionFile(
×
183
                        w.cfg.WatchtowerKeyPath, 0600, w.cfg.EncryptKey,
×
184
                        encrypter,
×
185
                ),
×
186
                Type: w.cfg.Type,
×
187
        }
×
188

×
189
        addr, err := w.cfg.TorController.AddOnion(onionCfg)
×
190
        if err != nil {
×
191
                return err
×
192
        }
×
193

194
        // Append this address to ExternalIPs so that it will be exposed in
195
        // tower info calls.
196
        w.cfg.ExternalIPs = append(w.cfg.ExternalIPs, addr)
×
197

×
198
        return nil
×
199
}
200

201
// PubKey returns the public key for the watchtower used to authentication and
202
// encrypt traffic with clients.
203
//
204
// NOTE: Part of the watchtowerrpc.WatchtowerBackend interface.
UNCOV
205
func (w *Standalone) PubKey() *btcec.PublicKey {
×
UNCOV
206
        return w.cfg.NodeKeyECDH.PubKey()
×
UNCOV
207
}
×
208

209
// ListeningAddrs returns the listening addresses where the watchtower server
210
// can accept client connections.
211
//
212
// NOTE: Part of the watchtowerrpc.WatchtowerBackend interface.
UNCOV
213
func (w *Standalone) ListeningAddrs() []net.Addr {
×
UNCOV
214
        addrs := make([]net.Addr, 0, len(w.listeners))
×
UNCOV
215
        for _, listener := range w.listeners {
×
UNCOV
216
                addrs = append(addrs, listener.Addr())
×
UNCOV
217
        }
×
218

UNCOV
219
        return addrs
×
220
}
221

222
// ExternalIPs returns the addresses where the watchtower can be reached by
223
// clients externally.
224
//
225
// NOTE: Part of the watchtowerrpc.WatchtowerBackend interface.
UNCOV
226
func (w *Standalone) ExternalIPs() []net.Addr {
×
UNCOV
227
        addrs := make([]net.Addr, 0, len(w.cfg.ExternalIPs))
×
UNCOV
228
        addrs = append(addrs, w.cfg.ExternalIPs...)
×
UNCOV
229

×
UNCOV
230
        return addrs
×
UNCOV
231
}
×
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