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

lightningnetwork / lnd / 11954082915

21 Nov 2024 01:20PM UTC coverage: 59.327% (+0.6%) from 58.776%
11954082915

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

1940 of 2984 new or added lines in 44 files covered. (65.01%)

226 existing lines in 37 files now uncovered.

135234 of 227947 relevant lines covered (59.33%)

19316.75 hits per line

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

22.56
/lnrpc/devrpc/dev_server.go
1
//go:build dev
2
// +build dev
3

4
package devrpc
5

6
import (
7
        "context"
8
        "encoding/hex"
9
        "fmt"
10
        "strconv"
11
        "strings"
12
        "sync/atomic"
13
        "time"
14

15
        "github.com/btcsuite/btcd/btcutil"
16
        "github.com/btcsuite/btcd/chaincfg/chainhash"
17
        "github.com/btcsuite/btcd/wire"
18
        "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
19
        "github.com/lightningnetwork/lnd/channeldb"
20
        "github.com/lightningnetwork/lnd/channeldb/models"
21
        "github.com/lightningnetwork/lnd/lncfg"
22
        "github.com/lightningnetwork/lnd/lnrpc"
23
        "github.com/lightningnetwork/lnd/lnwire"
24
        "google.golang.org/grpc"
25
        "gopkg.in/macaroon-bakery.v2/bakery"
26
)
27

28
const (
29
        // subServerName is the name of the sub rpc server. We'll use this name
30
        // to register ourselves, and we also require that the main
31
        // SubServerConfigDispatcher instance recognize tt as the name of our
32
        // RPC service.
33
        subServerName = "DevRPC"
34
)
35

36
var (
37
        // macPermissions maps RPC calls to the permissions they require.
38
        macPermissions = map[string][]bakery.Op{
39
                "/devrpc.Dev/ImportGraph": {{
40
                        Entity: "offchain",
41
                        Action: "write",
42
                }},
43
        }
44
)
45

46
// ServerShell is a shell struct holding a reference to the actual sub-server.
47
// It is used to register the gRPC sub-server with the root server before we
48
// have the necessary dependencies to populate the actual sub-server.
49
type ServerShell struct {
50
        DevServer
51
}
52

53
// Server is a sub-server of the main RPC server: the dev RPC. This sub
54
// RPC server allows developers to set and query LND state that is not possible
55
// during normal operation.
56
type Server struct {
57
        injected int32 // To be used atomically.
58
        shutdown int32 // To be used atomically.
59

60
        // Required by the grpc-gateway/v2 library for forward compatibility.
61
        // Must be after the atomically used variables to not break struct
62
        // alignment.
63
        UnimplementedDevServer
64

65
        cfg *Config
66
}
67

68
// A compile time check to ensure that Server fully implements the
69
// DevServer gRPC service.
70
var _ DevServer = (*Server)(nil)
71

72
// New returns a new instance of the devrpc Dev sub-server. We also return the
73
// set of permissions for the macaroons that we may create within this method.
74
// If the macaroons we need aren't found in the filepath, then we'll create them
75
// on start up. If we're unable to locate, or create the macaroons we need, then
76
// we'll return with an error.
77
func New() (*Server, lnrpc.MacaroonPerms, error) {
4✔
78
        // We don't create any new macaroons for this subserver, instead reuse
4✔
79
        // existing onchain/offchain permissions.
4✔
80
        return &Server{cfg: &Config{}}, macPermissions, nil
4✔
81
}
4✔
82

83
// Stop signals any active goroutines for a graceful closure.
84
//
85
// NOTE: This is part of the lnrpc.SubServer interface.
86
func (s *Server) Stop() error {
4✔
87
        if atomic.AddInt32(&s.shutdown, 1) != 1 {
4✔
88
                return nil
×
89
        }
×
90

91
        return nil
4✔
92
}
93

94
// InjectDependencies populates the sub-server's dependencies. If the
95
// finalizeDependencies boolean is true, then the sub-server will finalize its
96
// dependencies and return an error if any required dependencies are missing.
97
//
98
// NOTE: This is part of the lnrpc.SubServer interface.
99
func (s *Server) InjectDependencies(
100
        configRegistry lnrpc.SubServerConfigDispatcher,
101
        finalizeDependencies bool) error {
4✔
102

4✔
103
        if finalizeDependencies && atomic.AddInt32(&s.injected, 1) != 1 {
4✔
NEW
104
                return lnrpc.ErrDependenciesFinalized
×
UNCOV
105
        }
×
106

107
        cfg, err := getConfig(configRegistry, finalizeDependencies)
4✔
108
        if err != nil {
4✔
NEW
109
                return err
×
NEW
110
        }
×
111

112
        s.cfg = cfg
4✔
113

4✔
114
        return nil
4✔
115
}
116

117
// Name returns a unique string representation of the sub-server. This can be
118
// used to identify the sub-server and also de-duplicate them.
119
//
120
// NOTE: This is part of the lnrpc.SubServer interface.
121
func (s *Server) Name() string {
4✔
122
        return subServerName
4✔
123
}
4✔
124

125
// RegisterWithRootServer will be called by the root gRPC server to direct a
126
// sub RPC server to register itself with the main gRPC root server. Until this
127
// is called, each sub-server won't be able to have
128
// requests routed towards it.
129
//
130
// NOTE: This is part of the lnrpc.GrpcHandler interface.
131
func (r *ServerShell) RegisterWithRootServer(grpcServer *grpc.Server) error {
4✔
132
        // We make sure that we register it with the main gRPC server to ensure
4✔
133
        // all our methods are routed properly.
4✔
134
        RegisterDevServer(grpcServer, r)
4✔
135

4✔
136
        log.Debugf("DEV RPC server successfully register with root the " +
4✔
137
                "gRPC server")
4✔
138

4✔
139
        return nil
4✔
140
}
4✔
141

142
// RegisterWithRestServer will be called by the root REST mux to direct a sub
143
// RPC server to register itself with the main REST mux server. Until this is
144
// called, each sub-server won't be able to have requests routed towards it.
145
//
146
// NOTE: This is part of the lnrpc.GrpcHandler interface.
147
func (r *ServerShell) RegisterWithRestServer(ctx context.Context,
148
        mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error {
4✔
149

4✔
150
        // We make sure that we register it with the main REST server to ensure
4✔
151
        // all our methods are routed properly.
4✔
152
        err := RegisterDevHandlerFromEndpoint(ctx, mux, dest, opts)
4✔
153
        if err != nil {
4✔
154
                log.Errorf("Could not register DEV REST server with the root "+
×
155
                        "REST server: %v", err)
×
156
                return err
×
157
        }
×
158

159
        log.Debugf("DEV REST server successfully registered with the root " +
4✔
160
                "REST server")
4✔
161
        return nil
4✔
162
}
163

164
// CreateSubServer creates an instance of the sub-server, and returns the
165
// macaroon permissions that the sub-server wishes to pass on to the root server
166
// for all methods routed towards it.
167
//
168
// NOTE: This is part of the lnrpc.GrpcHandler interface.
169
func (r *ServerShell) CreateSubServer() (
170
        lnrpc.SubServer, lnrpc.MacaroonPerms, error) {
4✔
171

4✔
172
        subServer, macPermissions, err := New()
4✔
173
        if err != nil {
4✔
174
                return nil, nil, err
×
175
        }
×
176

177
        r.DevServer = subServer
4✔
178
        return subServer, macPermissions, nil
4✔
179
}
180

181
func parseOutPoint(s string) (*wire.OutPoint, error) {
×
182
        split := strings.Split(s, ":")
×
183
        if len(split) != 2 {
×
184
                return nil, fmt.Errorf("expecting outpoint to be in format of: " +
×
185
                        "txid:index")
×
186
        }
×
187

188
        index, err := strconv.ParseInt(split[1], 10, 32)
×
189
        if err != nil {
×
190
                return nil, fmt.Errorf("unable to decode output index: %w", err)
×
191
        }
×
192

193
        txid, err := chainhash.NewHashFromStr(split[0])
×
194
        if err != nil {
×
195
                return nil, fmt.Errorf("unable to parse hex string: %w", err)
×
196
        }
×
197

198
        return &wire.OutPoint{
×
199
                Hash:  *txid,
×
200
                Index: uint32(index),
×
201
        }, nil
×
202
}
203

204
func parsePubKey(pubKeyStr string) ([33]byte, error) {
×
205
        var pubKey [33]byte
×
206
        pubKeyBytes, err := hex.DecodeString(pubKeyStr)
×
207
        if err != nil || len(pubKeyBytes) != 33 {
×
208
                return pubKey, fmt.Errorf("invalid pubkey: %v", pubKeyStr)
×
209
        }
×
210

211
        copy(pubKey[:], pubKeyBytes)
×
212
        return pubKey, nil
×
213
}
214

215
// ImportGraph imports a graph dump (without auth proofs).
216
//
217
// NOTE: Part of the DevServer interface.
218
func (s *Server) ImportGraph(ctx context.Context,
219
        graph *lnrpc.ChannelGraph) (*ImportGraphResponse, error) {
×
220

×
221
        // Obtain the pointer to the global singleton channel graph.
×
222
        graphDB := s.cfg.GraphDB
×
223

×
224
        var err error
×
225
        for _, rpcNode := range graph.Nodes {
×
226
                node := &channeldb.LightningNode{
×
227
                        HaveNodeAnnouncement: true,
×
228
                        LastUpdate: time.Unix(
×
229
                                int64(rpcNode.LastUpdate), 0,
×
230
                        ),
×
231
                        Alias: rpcNode.Alias,
×
232
                }
×
233

×
234
                node.PubKeyBytes, err = parsePubKey(rpcNode.PubKey)
×
235
                if err != nil {
×
236
                        return nil, err
×
237
                }
×
238

239
                featureBits := make([]lnwire.FeatureBit, 0, len(rpcNode.Features))
×
240
                featureNames := make(map[lnwire.FeatureBit]string)
×
241

×
242
                for featureBit, feature := range rpcNode.Features {
×
243
                        featureBits = append(
×
244
                                featureBits, lnwire.FeatureBit(featureBit),
×
245
                        )
×
246

×
247
                        featureNames[lnwire.FeatureBit(featureBit)] = feature.Name
×
248
                }
×
249

250
                featureVector := lnwire.NewRawFeatureVector(featureBits...)
×
251
                node.Features = lnwire.NewFeatureVector(
×
252
                        featureVector, featureNames,
×
253
                )
×
254

×
255
                node.Color, err = lncfg.ParseHexColor(rpcNode.Color)
×
256
                if err != nil {
×
257
                        return nil, err
×
258
                }
×
259

260
                if err := graphDB.AddLightningNode(node); err != nil {
×
261
                        return nil, fmt.Errorf("unable to add node %v: %w",
×
262
                                rpcNode.PubKey, err)
×
263
                }
×
264

265
                log.Debugf("Imported node: %v", rpcNode.PubKey)
×
266
        }
267

268
        for _, rpcEdge := range graph.Edges {
×
269
                rpcEdge := rpcEdge
×
270

×
271
                edge := &models.ChannelEdgeInfo{
×
272
                        ChannelID: rpcEdge.ChannelId,
×
273
                        ChainHash: *s.cfg.ActiveNetParams.GenesisHash,
×
274
                        Capacity:  btcutil.Amount(rpcEdge.Capacity),
×
275
                }
×
276

×
277
                edge.NodeKey1Bytes, err = parsePubKey(rpcEdge.Node1Pub)
×
278
                if err != nil {
×
279
                        return nil, err
×
280
                }
×
281

282
                edge.NodeKey2Bytes, err = parsePubKey(rpcEdge.Node2Pub)
×
283
                if err != nil {
×
284
                        return nil, err
×
285
                }
×
286

287
                channelPoint, err := parseOutPoint(rpcEdge.ChanPoint)
×
288
                if err != nil {
×
289
                        return nil, err
×
290
                }
×
291
                edge.ChannelPoint = *channelPoint
×
292

×
293
                if err := graphDB.AddChannelEdge(edge); err != nil {
×
294
                        return nil, fmt.Errorf("unable to add edge %v: %w",
×
295
                                rpcEdge.ChanPoint, err)
×
296
                }
×
297

298
                makePolicy := func(rpcPolicy *lnrpc.RoutingPolicy) *models.ChannelEdgePolicy { //nolint:lll
×
299
                        policy := &models.ChannelEdgePolicy{
×
300
                                ChannelID: rpcEdge.ChannelId,
×
301
                                LastUpdate: time.Unix(
×
302
                                        int64(rpcPolicy.LastUpdate), 0,
×
303
                                ),
×
304
                                TimeLockDelta: uint16(
×
305
                                        rpcPolicy.TimeLockDelta,
×
306
                                ),
×
307
                                MinHTLC: lnwire.MilliSatoshi(
×
308
                                        rpcPolicy.MinHtlc,
×
309
                                ),
×
310
                                FeeBaseMSat: lnwire.MilliSatoshi(
×
311
                                        rpcPolicy.FeeBaseMsat,
×
312
                                ),
×
313
                                FeeProportionalMillionths: lnwire.MilliSatoshi(
×
314
                                        rpcPolicy.FeeRateMilliMsat,
×
315
                                ),
×
316
                        }
×
317
                        if rpcPolicy.MaxHtlcMsat > 0 {
×
318
                                policy.MaxHTLC = lnwire.MilliSatoshi(
×
319
                                        rpcPolicy.MaxHtlcMsat,
×
320
                                )
×
321
                                policy.MessageFlags |=
×
322
                                        lnwire.ChanUpdateRequiredMaxHtlc
×
323
                        }
×
324

325
                        return policy
×
326
                }
327

328
                if rpcEdge.Node1Policy != nil {
×
329
                        policy := makePolicy(rpcEdge.Node1Policy)
×
330
                        policy.ChannelFlags = 0
×
331
                        if err := graphDB.UpdateEdgePolicy(policy); err != nil {
×
332
                                return nil, fmt.Errorf(
×
333
                                        "unable to update policy: %v", err)
×
334
                        }
×
335
                }
336

337
                if rpcEdge.Node2Policy != nil {
×
338
                        policy := makePolicy(rpcEdge.Node2Policy)
×
339
                        policy.ChannelFlags = 1
×
340
                        if err := graphDB.UpdateEdgePolicy(policy); err != nil {
×
341
                                return nil, fmt.Errorf(
×
342
                                        "unable to update policy: %v", err)
×
343
                        }
×
344
                }
345

346
                log.Debugf("Added edge: %v", rpcEdge.ChannelId)
×
347
        }
348

349
        return &ImportGraphResponse{}, nil
×
350
}
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