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

lightningnetwork / lnd / 12412879685

19 Dec 2024 12:40PM UTC coverage: 58.744% (+0.09%) from 58.653%
12412879685

Pull #8754

github

ViktorTigerstrom
itest: wrap deriveCustomScopeAccounts at 80 chars

This commit fixes that word wrapping for the deriveCustomScopeAccounts
function docs, and ensures that it wraps at 80 characters or less.
Pull Request #8754: Add `Outbound` Remote Signer implementation

1858 of 2816 new or added lines in 47 files covered. (65.98%)

267 existing lines in 51 files now uncovered.

136038 of 231578 relevant lines covered (58.74%)

19020.65 hits per line

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

65.71
/lncfg/remotesigner.go
1
package lncfg
2

3
import (
4
        "fmt"
5
        "time"
6
)
7

8
const (
9
        // DefaultRemoteSignerRPCTimeout is the default connection timeout
10
        // that is used when connecting to the remote signer or watch-only node
11
        // through RPC.
12
        DefaultRemoteSignerRPCTimeout = 5 * time.Second
13

14
        // DefaultRequestTimeout is the default timeout used for requests to and
15
        // from the remote signer.
16
        DefaultRequestTimeout = 5 * time.Second
17

18
        // DefaultStartupTimeout is the default startup timeout used when a
19
        // watch-only node with 'remotesigner.allowinboundconnection' set to
20
        // true waits for the remote signer to connect.
21
        DefaultStartupTimeout = 5 * time.Minute
22
)
23

24
// RemoteSigner holds the configuration options for how to connect to a remote
25
// signer. Only a watch-only node specifies this config.
26
//
27
//nolint:ll
28
type RemoteSigner struct {
29
        // Enable signals if this node is a watch-only node in a remote signer
30
        // setup.
31
        Enable bool `long:"enable" description:"Use a remote signer for signing any on-chain related transactions or messages. Only recommended if local wallet is initialized as watch-only. Remote signer must use the same seed/root key as the local watch-only wallet but must have private keys."`
32

33
        // AllowInboundConnection is true if the remote signer node will connect
34
        // to this node.
35
        AllowInboundConnection bool `long:"allowinboundconnection" description:"Signals that we allow an inbound connection from a remote signer to this node."`
36

37
        // MigrateWatchOnly migrates the wallet to a watch-only wallet by
38
        // purging all private keys from the wallet after first unlock with this
39
        // flag.
40
        MigrateWatchOnly bool `long:"migrate-wallet-to-watch-only" description:"If a wallet with private key material already exists, migrate it into a watch-only wallet on first startup. WARNING: This cannot be undone! Make sure you have backed up your seed before you use this flag! All private keys will be purged from the wallet after first unlock with this flag!"`
41

42
        // ConnectionCfg holds the connection configuration options that the
43
        // watch-only node will use when setting up the connection to the remote
44
        // signer.
45
        ConnectionCfg
46

47
        // inboundWatchOnlyCfg holds the configuration options specifically
48
        // used when the watch-only node expects an inbound connection from
49
        // the remote signer.
50
        inboundWatchOnlyCfg
51
}
52

53
// DefaultRemoteSignerCfg returns the default RemoteSigner config.
54
func DefaultRemoteSignerCfg() *RemoteSigner {
4✔
55
        return &RemoteSigner{
4✔
56
                Enable:                 false,
4✔
57
                AllowInboundConnection: false,
4✔
58
                ConnectionCfg:          defaultConnectionCfg(),
4✔
59
                inboundWatchOnlyCfg: inboundWatchOnlyCfg{
4✔
60
                        StartupTimeout: DefaultStartupTimeout,
4✔
61
                },
4✔
62
        }
4✔
63
}
4✔
64

65
// Validate checks the values configured for our remote RPC signer.
66
func (r *RemoteSigner) Validate() error {
3✔
67
        if r.MigrateWatchOnly && !r.Enable {
3✔
NEW
68
                return fmt.Errorf("remote signer: cannot turn on wallet " +
×
NEW
69
                        "migration to watch-only if remote signing is not " +
×
NEW
70
                        "enabled")
×
NEW
71
        }
×
72

73
        if !r.Enable {
6✔
74
                return nil
3✔
75
        }
3✔
76

77
        if r.AllowInboundConnection {
6✔
78
                if r.StartupTimeout < time.Second {
3✔
NEW
79
                        return fmt.Errorf("remotesigner.startuptimeout of "+
×
NEW
80
                                "%v is invalid, cannot be smaller than %v",
×
NEW
81
                                r.Timeout, time.Second)
×
NEW
82
                }
×
83

84
                return nil
3✔
85
        }
86

87
        // Else, we are in outbound mode, so we verify the connection config.
88
        err := r.ConnectionCfg.Validate()
3✔
89
        if err != nil {
3✔
NEW
90
                return fmt.Errorf("remotesigner.%w", err)
×
NEW
91
        }
×
92

93
        return nil
3✔
94
}
95

96
// inboundWatchOnlyCfg holds the configuration options specific for watch-only
97
// nodes with the allowinboundconnection` option set.
98
//
99
//nolint:ll
100
type inboundWatchOnlyCfg struct {
101
        StartupTimeout time.Duration `long:"startuptimeout" description:"The time the watch-only node will wait for the remote signer to connect during startup. If the timeout expires before the remote signer connects, the watch-only node will shut down. Valid time units are {s, m, h}."`
102
}
103

104
// WatchOnlyNode holds the configuration options for how to connect to a watch
105
// only node. Only a signer node specifies this config.
106
//
107
//nolint:ll
108
type WatchOnlyNode struct {
109
        // Enable signals if this node a signer node and is expected to connect
110
        // to a watch-only node.
111
        Enable bool `long:"enable" description:"Signals that this node functions as a remote signer that will to connect with a watch-only node."`
112

113
        // ConnectionCfg holds the connection configuration options that the
114
        // remote signer node will use when setting up the connection to the
115
        // watch-only node.
116
        ConnectionCfg
117
}
118

119
// DefaultWatchOnlyNodeCfg returns the default WatchOnlyNode config.
120
func DefaultWatchOnlyNodeCfg() *WatchOnlyNode {
4✔
121
        return &WatchOnlyNode{
4✔
122
                Enable: false,
4✔
123
        }
4✔
124
}
4✔
125

126
// Validate checks the values set in the WatchOnlyNode config are valid.
127
func (w *WatchOnlyNode) Validate() error {
3✔
128
        if !w.Enable {
6✔
129
                return nil
3✔
130
        }
3✔
131

132
        err := w.ConnectionCfg.Validate()
3✔
133
        if err != nil {
3✔
NEW
134
                return fmt.Errorf("watchonlynode.%w", err)
×
NEW
135
        }
×
136

137
        return nil
3✔
138
}
139

140
// ConnectionCfg holds the configuration options required when setting up a
141
// connection to either a remote signer or watch-only node, depending on which
142
// side makes the outbound connection.
143
//
144
//nolint:ll
145
type ConnectionCfg struct {
146
        RPCHost        string        `long:"rpchost" description:"The RPC host:port of the remote signer or watch-only node. For watch-only nodes with 'remotesigner.allowinboundconnection' set to false (the default value if not specifically set), this should be set to the remote signer's RPC host:port. For remote signer nodes connecting to a watch-only node with 'remotesigner.allowinboundconnection' set to true, this should be set to the watch-only node's RPC host:port."`
147
        MacaroonPath   string        `long:"macaroonpath" description:"The macaroon to use for authenticating with the remote signer or the watch-only node. For watch-only nodes with 'remotesigner.allowinboundconnection' set to false (the default value if not specifically set), this should be set to the remote signer's macaroon. For remote signer nodes connecting to a watch-only node with 'remotesigner.allowinboundconnection' set to true, this should be set to the watch-only node's macaroon."`
148
        TLSCertPath    string        `long:"tlscertpath" description:"The TLS certificate to use for establishing the remote signer's or watch-only node's identity. For watch-only nodes with 'remotesigner.allowinboundconnection' set to false (the default value if not specifically set), this should be set to the remote signer's TLS certificate. For remote signer nodes connecting to a watch-only node with 'remotesigner.allowinboundconnection' set to true, this should be set to the watch-only node's TLS certificate."`
149
        Timeout        time.Duration `long:"timeout" description:"The timeout for making the connection to the remote signer or watch-only node, depending on whether the node acts as a watch-only node or a signer. Valid time units are {s, m, h}."`
150
        RequestTimeout time.Duration `long:"requesttimeout" description:"The time we will wait when making requests to the remote signer or watch-only node, depending on whether the node acts as a watch-only node or a signer. Valid time units are {s, m, h}."`
151
}
152

153
// defaultConnectionCfg returns the default ConnectionCfg config.
154
func defaultConnectionCfg() ConnectionCfg {
4✔
155
        return ConnectionCfg{
4✔
156
                Timeout:        DefaultRemoteSignerRPCTimeout,
4✔
157
                RequestTimeout: DefaultRequestTimeout,
4✔
158
        }
4✔
159
}
4✔
160

161
// Validate checks the values set in the ConnectionCfg config are valid.
162
func (c *ConnectionCfg) Validate() error {
3✔
163
        if c.Timeout < time.Millisecond {
3✔
NEW
164
                return fmt.Errorf("timeout of %v is invalid, cannot be "+
×
NEW
165
                        "smaller than %v", c.Timeout, time.Millisecond)
×
NEW
166
        }
×
167

168
        if c.RequestTimeout < time.Second {
3✔
NEW
169
                return fmt.Errorf("requesttimeout of %v is invalid, cannot "+
×
NEW
170
                        "be smaller than %v", c.Timeout, time.Second)
×
NEW
171
        }
×
172

173
        if c.RPCHost == "" {
3✔
NEW
174
                return fmt.Errorf("rpchost must be set")
×
NEW
175
        }
×
176

177
        if c.MacaroonPath == "" {
3✔
NEW
178
                return fmt.Errorf("macaroonpath must be set")
×
NEW
179
        }
×
180

181
        if c.TLSCertPath == "" {
3✔
NEW
182
                return fmt.Errorf("tlscertpath must be set")
×
UNCOV
183
        }
×
184

185
        return nil
3✔
186
}
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