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

lightningnetwork / lnd / 13236757158

10 Feb 2025 08:39AM UTC coverage: 57.649% (-1.2%) from 58.815%
13236757158

Pull #9493

github

ziggie1984
lncli: for some cmds we don't replace the data of the response.

For some cmds it is not very practical to replace the json output
because we might pipe it into other commands. For example when
creating the route we want to pipe it into sendtoRoute.
Pull Request #9493: For some lncli cmds we should not replace the content with other data

0 of 9 new or added lines in 2 files covered. (0.0%)

19535 existing lines in 252 files now uncovered.

103517 of 179563 relevant lines covered (57.65%)

24878.49 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