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

lightningnetwork / lnd / 12281843618

11 Dec 2024 05:38PM UTC coverage: 49.477% (-0.06%) from 49.54%
12281843618

Pull #9242

github

aakselrod
docs: update release-notes for 0.19.0
Pull Request #9242: Reapply #8644

6 of 27 new or added lines in 2 files covered. (22.22%)

170 existing lines in 20 files now uncovered.

100257 of 202632 relevant lines covered (49.48%)

1.54 hits per line

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

70.52
/rpcserver.go
1
package lnd
2

3
import (
4
        "bytes"
5
        "context"
6
        "encoding/hex"
7
        "errors"
8
        "fmt"
9
        "io"
10
        "math"
11
        "net"
12
        "net/http"
13
        "os"
14
        "path/filepath"
15
        "runtime"
16
        "sort"
17
        "strconv"
18
        "strings"
19
        "sync"
20
        "sync/atomic"
21
        "time"
22

23
        "github.com/btcsuite/btcd/blockchain"
24
        "github.com/btcsuite/btcd/btcec/v2"
25
        "github.com/btcsuite/btcd/btcec/v2/ecdsa"
26
        "github.com/btcsuite/btcd/btcutil"
27
        "github.com/btcsuite/btcd/btcutil/psbt"
28
        "github.com/btcsuite/btcd/chaincfg"
29
        "github.com/btcsuite/btcd/chaincfg/chainhash"
30
        "github.com/btcsuite/btcd/txscript"
31
        "github.com/btcsuite/btcd/wire"
32
        "github.com/btcsuite/btcwallet/waddrmgr"
33
        "github.com/btcsuite/btcwallet/wallet"
34
        "github.com/btcsuite/btcwallet/wallet/txauthor"
35
        "github.com/davecgh/go-spew/spew"
36
        proxy "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
37
        "github.com/lightningnetwork/lnd/autopilot"
38
        "github.com/lightningnetwork/lnd/build"
39
        "github.com/lightningnetwork/lnd/chainreg"
40
        "github.com/lightningnetwork/lnd/chanacceptor"
41
        "github.com/lightningnetwork/lnd/chanbackup"
42
        "github.com/lightningnetwork/lnd/chanfitness"
43
        "github.com/lightningnetwork/lnd/channeldb"
44
        "github.com/lightningnetwork/lnd/channelnotifier"
45
        "github.com/lightningnetwork/lnd/clock"
46
        "github.com/lightningnetwork/lnd/contractcourt"
47
        "github.com/lightningnetwork/lnd/discovery"
48
        "github.com/lightningnetwork/lnd/feature"
49
        "github.com/lightningnetwork/lnd/fn/v2"
50
        "github.com/lightningnetwork/lnd/funding"
51
        "github.com/lightningnetwork/lnd/graph"
52
        graphdb "github.com/lightningnetwork/lnd/graph/db"
53
        "github.com/lightningnetwork/lnd/graph/db/models"
54
        "github.com/lightningnetwork/lnd/graph/graphsession"
55
        "github.com/lightningnetwork/lnd/htlcswitch"
56
        "github.com/lightningnetwork/lnd/htlcswitch/hop"
57
        "github.com/lightningnetwork/lnd/input"
58
        "github.com/lightningnetwork/lnd/invoices"
59
        "github.com/lightningnetwork/lnd/keychain"
60
        "github.com/lightningnetwork/lnd/kvdb"
61
        "github.com/lightningnetwork/lnd/labels"
62
        "github.com/lightningnetwork/lnd/lncfg"
63
        "github.com/lightningnetwork/lnd/lnrpc"
64
        "github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
65
        "github.com/lightningnetwork/lnd/lnrpc/routerrpc"
66
        "github.com/lightningnetwork/lnd/lnrpc/walletrpc"
67
        "github.com/lightningnetwork/lnd/lntypes"
68
        "github.com/lightningnetwork/lnd/lnutils"
69
        "github.com/lightningnetwork/lnd/lnwallet"
70
        "github.com/lightningnetwork/lnd/lnwallet/btcwallet"
71
        "github.com/lightningnetwork/lnd/lnwallet/chainfee"
72
        "github.com/lightningnetwork/lnd/lnwallet/chancloser"
73
        "github.com/lightningnetwork/lnd/lnwallet/chanfunding"
74
        "github.com/lightningnetwork/lnd/lnwire"
75
        "github.com/lightningnetwork/lnd/macaroons"
76
        "github.com/lightningnetwork/lnd/peer"
77
        "github.com/lightningnetwork/lnd/peernotifier"
78
        "github.com/lightningnetwork/lnd/record"
79
        "github.com/lightningnetwork/lnd/routing"
80
        "github.com/lightningnetwork/lnd/routing/blindedpath"
81
        "github.com/lightningnetwork/lnd/routing/route"
82
        "github.com/lightningnetwork/lnd/rpcperms"
83
        "github.com/lightningnetwork/lnd/signal"
84
        "github.com/lightningnetwork/lnd/sweep"
85
        "github.com/lightningnetwork/lnd/tlv"
86
        "github.com/lightningnetwork/lnd/watchtower"
87
        "github.com/lightningnetwork/lnd/zpay32"
88
        "github.com/tv42/zbase32"
89
        "google.golang.org/grpc"
90
        "google.golang.org/grpc/codes"
91
        "google.golang.org/grpc/status"
92
        "google.golang.org/protobuf/proto"
93
        "gopkg.in/macaroon-bakery.v2/bakery"
94
)
95

96
const (
97
        // defaultNumBlocksEstimate is the number of blocks that we fall back
98
        // to issuing an estimate for if a fee pre fence doesn't specify an
99
        // explicit conf target or fee rate.
100
        defaultNumBlocksEstimate = 6
101
)
102

103
var (
104
        // readPermissions is a slice of all entities that allow read
105
        // permissions for authorization purposes, all lowercase.
106
        readPermissions = []bakery.Op{
107
                {
108
                        Entity: "onchain",
109
                        Action: "read",
110
                },
111
                {
112
                        Entity: "offchain",
113
                        Action: "read",
114
                },
115
                {
116
                        Entity: "address",
117
                        Action: "read",
118
                },
119
                {
120
                        Entity: "message",
121
                        Action: "read",
122
                },
123
                {
124
                        Entity: "peers",
125
                        Action: "read",
126
                },
127
                {
128
                        Entity: "info",
129
                        Action: "read",
130
                },
131
                {
132
                        Entity: "invoices",
133
                        Action: "read",
134
                },
135
                {
136
                        Entity: "signer",
137
                        Action: "read",
138
                },
139
                {
140
                        Entity: "macaroon",
141
                        Action: "read",
142
                },
143
        }
144

145
        // writePermissions is a slice of all entities that allow write
146
        // permissions for authorization purposes, all lowercase.
147
        writePermissions = []bakery.Op{
148
                {
149
                        Entity: "onchain",
150
                        Action: "write",
151
                },
152
                {
153
                        Entity: "offchain",
154
                        Action: "write",
155
                },
156
                {
157
                        Entity: "address",
158
                        Action: "write",
159
                },
160
                {
161
                        Entity: "message",
162
                        Action: "write",
163
                },
164
                {
165
                        Entity: "peers",
166
                        Action: "write",
167
                },
168
                {
169
                        Entity: "info",
170
                        Action: "write",
171
                },
172
                {
173
                        Entity: "invoices",
174
                        Action: "write",
175
                },
176
                {
177
                        Entity: "signer",
178
                        Action: "generate",
179
                },
180
                {
181
                        Entity: "macaroon",
182
                        Action: "generate",
183
                },
184
                {
185
                        Entity: "macaroon",
186
                        Action: "write",
187
                },
188
        }
189

190
        // invoicePermissions is a slice of all the entities that allows a user
191
        // to only access calls that are related to invoices, so: streaming
192
        // RPCs, generating, and listening invoices.
193
        invoicePermissions = []bakery.Op{
194
                {
195
                        Entity: "invoices",
196
                        Action: "read",
197
                },
198
                {
199
                        Entity: "invoices",
200
                        Action: "write",
201
                },
202
                {
203
                        Entity: "address",
204
                        Action: "read",
205
                },
206
                {
207
                        Entity: "address",
208
                        Action: "write",
209
                },
210
                {
211
                        Entity: "onchain",
212
                        Action: "read",
213
                },
214
        }
215

216
        // TODO(guggero): Refactor into constants that are used for all
217
        // permissions in this file. Also expose the list of possible
218
        // permissions in an RPC when per RPC permissions are
219
        // implemented.
220
        validActions  = []string{"read", "write", "generate"}
221
        validEntities = []string{
222
                "onchain", "offchain", "address", "message",
223
                "peers", "info", "invoices", "signer", "macaroon",
224
                macaroons.PermissionEntityCustomURI,
225
        }
226

227
        // If the --no-macaroons flag is used to start lnd, the macaroon service
228
        // is not initialized. errMacaroonDisabled is then returned when
229
        // macaroon related services are used.
230
        errMacaroonDisabled = fmt.Errorf("macaroon authentication disabled, " +
231
                "remove --no-macaroons flag to enable")
232
)
233

234
// stringInSlice returns true if a string is contained in the given slice.
235
func stringInSlice(a string, slice []string) bool {
3✔
236
        for _, b := range slice {
6✔
237
                if b == a {
6✔
238
                        return true
3✔
239
                }
3✔
240
        }
241
        return false
3✔
242
}
243

244
// GetAllPermissions returns all the permissions required to interact with lnd.
245
func GetAllPermissions() []bakery.Op {
×
246
        allPerms := make([]bakery.Op, 0)
×
247

×
248
        // The map will help keep track of which specific permission pairs have
×
249
        // already been added to the slice.
×
250
        allPermsMap := make(map[string]map[string]struct{})
×
251

×
252
        for _, perms := range MainRPCServerPermissions() {
×
253
                for _, perm := range perms {
×
254
                        entity := perm.Entity
×
255
                        action := perm.Action
×
256

×
257
                        // If this specific entity-action permission pair isn't
×
258
                        // in the map yet. Add it to map, and the permission
×
259
                        // slice.
×
260
                        if acts, ok := allPermsMap[entity]; ok {
×
261
                                if _, ok := acts[action]; !ok {
×
262
                                        allPermsMap[entity][action] = struct{}{}
×
263

×
264
                                        allPerms = append(
×
265
                                                allPerms, perm,
×
266
                                        )
×
267
                                }
×
268
                        } else {
×
269
                                allPermsMap[entity] = make(map[string]struct{})
×
270
                                allPermsMap[entity][action] = struct{}{}
×
271
                                allPerms = append(allPerms, perm)
×
272
                        }
×
273
                }
274
        }
275

276
        return allPerms
×
277
}
278

279
// MainRPCServerPermissions returns a mapping of the main RPC server calls to
280
// the permissions they require.
281
func MainRPCServerPermissions() map[string][]bakery.Op {
3✔
282
        return map[string][]bakery.Op{
3✔
283
                "/lnrpc.Lightning/SendCoins": {{
3✔
284
                        Entity: "onchain",
3✔
285
                        Action: "write",
3✔
286
                }},
3✔
287
                "/lnrpc.Lightning/ListUnspent": {{
3✔
288
                        Entity: "onchain",
3✔
289
                        Action: "read",
3✔
290
                }},
3✔
291
                "/lnrpc.Lightning/SendMany": {{
3✔
292
                        Entity: "onchain",
3✔
293
                        Action: "write",
3✔
294
                }},
3✔
295
                "/lnrpc.Lightning/NewAddress": {{
3✔
296
                        Entity: "address",
3✔
297
                        Action: "write",
3✔
298
                }},
3✔
299
                "/lnrpc.Lightning/SignMessage": {{
3✔
300
                        Entity: "message",
3✔
301
                        Action: "write",
3✔
302
                }},
3✔
303
                "/lnrpc.Lightning/VerifyMessage": {{
3✔
304
                        Entity: "message",
3✔
305
                        Action: "read",
3✔
306
                }},
3✔
307
                "/lnrpc.Lightning/ConnectPeer": {{
3✔
308
                        Entity: "peers",
3✔
309
                        Action: "write",
3✔
310
                }},
3✔
311
                "/lnrpc.Lightning/DisconnectPeer": {{
3✔
312
                        Entity: "peers",
3✔
313
                        Action: "write",
3✔
314
                }},
3✔
315
                "/lnrpc.Lightning/OpenChannel": {{
3✔
316
                        Entity: "onchain",
3✔
317
                        Action: "write",
3✔
318
                }, {
3✔
319
                        Entity: "offchain",
3✔
320
                        Action: "write",
3✔
321
                }},
3✔
322
                "/lnrpc.Lightning/BatchOpenChannel": {{
3✔
323
                        Entity: "onchain",
3✔
324
                        Action: "write",
3✔
325
                }, {
3✔
326
                        Entity: "offchain",
3✔
327
                        Action: "write",
3✔
328
                }},
3✔
329
                "/lnrpc.Lightning/OpenChannelSync": {{
3✔
330
                        Entity: "onchain",
3✔
331
                        Action: "write",
3✔
332
                }, {
3✔
333
                        Entity: "offchain",
3✔
334
                        Action: "write",
3✔
335
                }},
3✔
336
                "/lnrpc.Lightning/CloseChannel": {{
3✔
337
                        Entity: "onchain",
3✔
338
                        Action: "write",
3✔
339
                }, {
3✔
340
                        Entity: "offchain",
3✔
341
                        Action: "write",
3✔
342
                }},
3✔
343
                "/lnrpc.Lightning/AbandonChannel": {{
3✔
344
                        Entity: "offchain",
3✔
345
                        Action: "write",
3✔
346
                }},
3✔
347
                "/lnrpc.Lightning/GetInfo": {{
3✔
348
                        Entity: "info",
3✔
349
                        Action: "read",
3✔
350
                }},
3✔
351
                "/lnrpc.Lightning/GetDebugInfo": {{
3✔
352
                        Entity: "info",
3✔
353
                        Action: "read",
3✔
354
                }, {
3✔
355
                        Entity: "offchain",
3✔
356
                        Action: "read",
3✔
357
                }, {
3✔
358
                        Entity: "onchain",
3✔
359
                        Action: "read",
3✔
360
                }, {
3✔
361
                        Entity: "peers",
3✔
362
                        Action: "read",
3✔
363
                }},
3✔
364
                "/lnrpc.Lightning/GetRecoveryInfo": {{
3✔
365
                        Entity: "info",
3✔
366
                        Action: "read",
3✔
367
                }},
3✔
368
                "/lnrpc.Lightning/ListPeers": {{
3✔
369
                        Entity: "peers",
3✔
370
                        Action: "read",
3✔
371
                }},
3✔
372
                "/lnrpc.Lightning/WalletBalance": {{
3✔
373
                        Entity: "onchain",
3✔
374
                        Action: "read",
3✔
375
                }},
3✔
376
                "/lnrpc.Lightning/EstimateFee": {{
3✔
377
                        Entity: "onchain",
3✔
378
                        Action: "read",
3✔
379
                }},
3✔
380
                "/lnrpc.Lightning/ChannelBalance": {{
3✔
381
                        Entity: "offchain",
3✔
382
                        Action: "read",
3✔
383
                }},
3✔
384
                "/lnrpc.Lightning/PendingChannels": {{
3✔
385
                        Entity: "offchain",
3✔
386
                        Action: "read",
3✔
387
                }},
3✔
388
                "/lnrpc.Lightning/ListChannels": {{
3✔
389
                        Entity: "offchain",
3✔
390
                        Action: "read",
3✔
391
                }},
3✔
392
                "/lnrpc.Lightning/SubscribeChannelEvents": {{
3✔
393
                        Entity: "offchain",
3✔
394
                        Action: "read",
3✔
395
                }},
3✔
396
                "/lnrpc.Lightning/ClosedChannels": {{
3✔
397
                        Entity: "offchain",
3✔
398
                        Action: "read",
3✔
399
                }},
3✔
400
                "/lnrpc.Lightning/SendPayment": {{
3✔
401
                        Entity: "offchain",
3✔
402
                        Action: "write",
3✔
403
                }},
3✔
404
                "/lnrpc.Lightning/SendPaymentSync": {{
3✔
405
                        Entity: "offchain",
3✔
406
                        Action: "write",
3✔
407
                }},
3✔
408
                "/lnrpc.Lightning/SendToRoute": {{
3✔
409
                        Entity: "offchain",
3✔
410
                        Action: "write",
3✔
411
                }},
3✔
412
                "/lnrpc.Lightning/SendToRouteSync": {{
3✔
413
                        Entity: "offchain",
3✔
414
                        Action: "write",
3✔
415
                }},
3✔
416
                "/lnrpc.Lightning/AddInvoice": {{
3✔
417
                        Entity: "invoices",
3✔
418
                        Action: "write",
3✔
419
                }},
3✔
420
                "/lnrpc.Lightning/LookupInvoice": {{
3✔
421
                        Entity: "invoices",
3✔
422
                        Action: "read",
3✔
423
                }},
3✔
424
                "/lnrpc.Lightning/ListInvoices": {{
3✔
425
                        Entity: "invoices",
3✔
426
                        Action: "read",
3✔
427
                }},
3✔
428
                "/lnrpc.Lightning/SubscribeInvoices": {{
3✔
429
                        Entity: "invoices",
3✔
430
                        Action: "read",
3✔
431
                }},
3✔
432
                "/lnrpc.Lightning/SubscribeTransactions": {{
3✔
433
                        Entity: "onchain",
3✔
434
                        Action: "read",
3✔
435
                }},
3✔
436
                "/lnrpc.Lightning/GetTransactions": {{
3✔
437
                        Entity: "onchain",
3✔
438
                        Action: "read",
3✔
439
                }},
3✔
440
                "/lnrpc.Lightning/DescribeGraph": {{
3✔
441
                        Entity: "info",
3✔
442
                        Action: "read",
3✔
443
                }},
3✔
444
                "/lnrpc.Lightning/GetNodeMetrics": {{
3✔
445
                        Entity: "info",
3✔
446
                        Action: "read",
3✔
447
                }},
3✔
448
                "/lnrpc.Lightning/GetChanInfo": {{
3✔
449
                        Entity: "info",
3✔
450
                        Action: "read",
3✔
451
                }},
3✔
452
                "/lnrpc.Lightning/GetNodeInfo": {{
3✔
453
                        Entity: "info",
3✔
454
                        Action: "read",
3✔
455
                }},
3✔
456
                "/lnrpc.Lightning/QueryRoutes": {{
3✔
457
                        Entity: "info",
3✔
458
                        Action: "read",
3✔
459
                }},
3✔
460
                "/lnrpc.Lightning/GetNetworkInfo": {{
3✔
461
                        Entity: "info",
3✔
462
                        Action: "read",
3✔
463
                }},
3✔
464
                "/lnrpc.Lightning/StopDaemon": {{
3✔
465
                        Entity: "info",
3✔
466
                        Action: "write",
3✔
467
                }},
3✔
468
                "/lnrpc.Lightning/SubscribeChannelGraph": {{
3✔
469
                        Entity: "info",
3✔
470
                        Action: "read",
3✔
471
                }},
3✔
472
                "/lnrpc.Lightning/ListPayments": {{
3✔
473
                        Entity: "offchain",
3✔
474
                        Action: "read",
3✔
475
                }},
3✔
476
                "/lnrpc.Lightning/DeletePayment": {{
3✔
477
                        Entity: "offchain",
3✔
478
                        Action: "write",
3✔
479
                }},
3✔
480
                "/lnrpc.Lightning/DeleteAllPayments": {{
3✔
481
                        Entity: "offchain",
3✔
482
                        Action: "write",
3✔
483
                }},
3✔
484
                "/lnrpc.Lightning/DebugLevel": {{
3✔
485
                        Entity: "info",
3✔
486
                        Action: "write",
3✔
487
                }},
3✔
488
                "/lnrpc.Lightning/DecodePayReq": {{
3✔
489
                        Entity: "offchain",
3✔
490
                        Action: "read",
3✔
491
                }},
3✔
492
                "/lnrpc.Lightning/FeeReport": {{
3✔
493
                        Entity: "offchain",
3✔
494
                        Action: "read",
3✔
495
                }},
3✔
496
                "/lnrpc.Lightning/UpdateChannelPolicy": {{
3✔
497
                        Entity: "offchain",
3✔
498
                        Action: "write",
3✔
499
                }},
3✔
500
                "/lnrpc.Lightning/ForwardingHistory": {{
3✔
501
                        Entity: "offchain",
3✔
502
                        Action: "read",
3✔
503
                }},
3✔
504
                "/lnrpc.Lightning/RestoreChannelBackups": {{
3✔
505
                        Entity: "offchain",
3✔
506
                        Action: "write",
3✔
507
                }},
3✔
508
                "/lnrpc.Lightning/ExportChannelBackup": {{
3✔
509
                        Entity: "offchain",
3✔
510
                        Action: "read",
3✔
511
                }},
3✔
512
                "/lnrpc.Lightning/VerifyChanBackup": {{
3✔
513
                        Entity: "offchain",
3✔
514
                        Action: "read",
3✔
515
                }},
3✔
516
                "/lnrpc.Lightning/ExportAllChannelBackups": {{
3✔
517
                        Entity: "offchain",
3✔
518
                        Action: "read",
3✔
519
                }},
3✔
520
                "/lnrpc.Lightning/SubscribeChannelBackups": {{
3✔
521
                        Entity: "offchain",
3✔
522
                        Action: "read",
3✔
523
                }},
3✔
524
                "/lnrpc.Lightning/ChannelAcceptor": {{
3✔
525
                        Entity: "onchain",
3✔
526
                        Action: "write",
3✔
527
                }, {
3✔
528
                        Entity: "offchain",
3✔
529
                        Action: "write",
3✔
530
                }},
3✔
531
                "/lnrpc.Lightning/BakeMacaroon": {{
3✔
532
                        Entity: "macaroon",
3✔
533
                        Action: "generate",
3✔
534
                }},
3✔
535
                "/lnrpc.Lightning/ListMacaroonIDs": {{
3✔
536
                        Entity: "macaroon",
3✔
537
                        Action: "read",
3✔
538
                }},
3✔
539
                "/lnrpc.Lightning/DeleteMacaroonID": {{
3✔
540
                        Entity: "macaroon",
3✔
541
                        Action: "write",
3✔
542
                }},
3✔
543
                "/lnrpc.Lightning/ListPermissions": {{
3✔
544
                        Entity: "info",
3✔
545
                        Action: "read",
3✔
546
                }},
3✔
547
                "/lnrpc.Lightning/CheckMacaroonPermissions": {{
3✔
548
                        Entity: "macaroon",
3✔
549
                        Action: "read",
3✔
550
                }},
3✔
551
                "/lnrpc.Lightning/SubscribePeerEvents": {{
3✔
552
                        Entity: "peers",
3✔
553
                        Action: "read",
3✔
554
                }},
3✔
555
                "/lnrpc.Lightning/FundingStateStep": {{
3✔
556
                        Entity: "onchain",
3✔
557
                        Action: "write",
3✔
558
                }, {
3✔
559
                        Entity: "offchain",
3✔
560
                        Action: "write",
3✔
561
                }},
3✔
562
                lnrpc.RegisterRPCMiddlewareURI: {{
3✔
563
                        Entity: "macaroon",
3✔
564
                        Action: "write",
3✔
565
                }},
3✔
566
                "/lnrpc.Lightning/SendCustomMessage": {{
3✔
567
                        Entity: "offchain",
3✔
568
                        Action: "write",
3✔
569
                }},
3✔
570
                "/lnrpc.Lightning/SubscribeCustomMessages": {{
3✔
571
                        Entity: "offchain",
3✔
572
                        Action: "read",
3✔
573
                }},
3✔
574
                "/lnrpc.Lightning/LookupHtlcResolution": {{
3✔
575
                        Entity: "offchain",
3✔
576
                        Action: "read",
3✔
577
                }},
3✔
578
                "/lnrpc.Lightning/ListAliases": {{
3✔
579
                        Entity: "offchain",
3✔
580
                        Action: "read",
3✔
581
                }},
3✔
582
        }
3✔
583
}
3✔
584

585
// AuxDataParser is an interface that is used to parse auxiliary custom data
586
// within RPC messages. This is used to transform binary blobs to human-readable
587
// JSON representations.
588
type AuxDataParser interface {
589
        // InlineParseCustomData replaces any custom data binary blob in the
590
        // given RPC message with its corresponding JSON formatted data. This
591
        // transforms the binary (likely TLV encoded) data to a human-readable
592
        // JSON representation (still as byte slice).
593
        InlineParseCustomData(msg proto.Message) error
594
}
595

596
// rpcServer is a gRPC, RPC front end to the lnd daemon.
597
// TODO(roasbeef): pagination support for the list-style calls
598
type rpcServer struct {
599
        started  int32 // To be used atomically.
600
        shutdown int32 // To be used atomically.
601

602
        // Required by the grpc-gateway/v2 library for forward compatibility.
603
        // Must be after the atomically used variables to not break struct
604
        // alignment.
605
        lnrpc.UnimplementedLightningServer
606

607
        server *server
608

609
        cfg *Config
610

611
        // subServers are a set of sub-RPC servers that use the same gRPC and
612
        // listening sockets as the main RPC server, but which maintain their
613
        // own independent service. This allows us to expose a set of
614
        // micro-service like abstractions to the outside world for users to
615
        // consume.
616
        subServers      []lnrpc.SubServer
617
        subGrpcHandlers []lnrpc.GrpcHandler
618

619
        // routerBackend contains the backend implementation of the router
620
        // rpc sub server.
621
        routerBackend *routerrpc.RouterBackend
622

623
        // chanPredicate is used in the bidirectional ChannelAcceptor streaming
624
        // method.
625
        chanPredicate chanacceptor.MultiplexAcceptor
626

627
        quit chan struct{}
628

629
        // macService is the macaroon service that we need to mint new
630
        // macaroons.
631
        macService *macaroons.Service
632

633
        // selfNode is our own pubkey.
634
        selfNode route.Vertex
635

636
        // interceptorChain is the interceptor added to our gRPC server.
637
        interceptorChain *rpcperms.InterceptorChain
638

639
        // implCfg is the configuration for some of the interfaces that can be
640
        // provided externally.
641
        implCfg *ImplementationCfg
642

643
        // interceptor is used to be able to request a shutdown
644
        interceptor signal.Interceptor
645

646
        graphCache        sync.RWMutex
647
        describeGraphResp *lnrpc.ChannelGraph
648
        graphCacheEvictor *time.Timer
649
}
650

651
// A compile time check to ensure that rpcServer fully implements the
652
// LightningServer gRPC service.
653
var _ lnrpc.LightningServer = (*rpcServer)(nil)
654

655
// newRPCServer creates and returns a new instance of the rpcServer. Before
656
// dependencies are added, this will be an non-functioning RPC server only to
657
// be used to register the LightningService with the gRPC server.
658
func newRPCServer(cfg *Config, interceptorChain *rpcperms.InterceptorChain,
659
        implCfg *ImplementationCfg, interceptor signal.Interceptor) *rpcServer {
3✔
660

3✔
661
        // We go trhough the list of registered sub-servers, and create a gRPC
3✔
662
        // handler for each. These are used to register with the gRPC server
3✔
663
        // before all dependencies are available.
3✔
664
        registeredSubServers := lnrpc.RegisteredSubServers()
3✔
665

3✔
666
        var subServerHandlers []lnrpc.GrpcHandler
3✔
667
        for _, subServer := range registeredSubServers {
6✔
668
                subServerHandlers = append(
3✔
669
                        subServerHandlers, subServer.NewGrpcHandler(),
3✔
670
                )
3✔
671
        }
3✔
672

673
        return &rpcServer{
3✔
674
                cfg:              cfg,
3✔
675
                subGrpcHandlers:  subServerHandlers,
3✔
676
                interceptorChain: interceptorChain,
3✔
677
                implCfg:          implCfg,
3✔
678
                quit:             make(chan struct{}, 1),
3✔
679
                interceptor:      interceptor,
3✔
680
        }
3✔
681
}
682

683
// addDeps populates all dependencies needed by the RPC server, and any
684
// of the sub-servers that it maintains. When this is done, the RPC server can
685
// be started, and start accepting RPC calls.
686
func (r *rpcServer) addDeps(s *server, macService *macaroons.Service,
687
        subServerCgs *subRPCServerConfigs, atpl *autopilot.Manager,
688
        invoiceRegistry *invoices.InvoiceRegistry, tower *watchtower.Standalone,
689
        chanPredicate chanacceptor.MultiplexAcceptor,
690
        invoiceHtlcModifier *invoices.HtlcModificationInterceptor) error {
3✔
691

3✔
692
        // Set up router rpc backend.
3✔
693
        selfNode, err := s.graphDB.SourceNode()
3✔
694
        if err != nil {
3✔
695
                return err
×
696
        }
×
697
        graph := s.graphDB
3✔
698

3✔
699
        routerBackend := &routerrpc.RouterBackend{
3✔
700
                SelfNode: selfNode.PubKeyBytes,
3✔
701
                FetchChannelCapacity: func(chanID uint64) (btcutil.Amount,
3✔
702
                        error) {
6✔
703

3✔
704
                        info, _, _, err := graph.FetchChannelEdgesByID(chanID)
3✔
705
                        if err != nil {
6✔
706
                                return 0, err
3✔
707
                        }
3✔
708
                        return info.Capacity, nil
3✔
709
                },
710
                FetchAmountPairCapacity: func(nodeFrom, nodeTo route.Vertex,
711
                        amount lnwire.MilliSatoshi) (btcutil.Amount, error) {
3✔
712

3✔
713
                        return routing.FetchAmountPairCapacity(
3✔
714
                                graphsession.NewRoutingGraph(graph),
3✔
715
                                selfNode.PubKeyBytes, nodeFrom, nodeTo, amount,
3✔
716
                        )
3✔
717
                },
3✔
718
                FetchChannelEndpoints: func(chanID uint64) (route.Vertex,
719
                        route.Vertex, error) {
×
720

×
721
                        info, _, _, err := graph.FetchChannelEdgesByID(
×
722
                                chanID,
×
723
                        )
×
724
                        if err != nil {
×
725
                                return route.Vertex{}, route.Vertex{},
×
726
                                        fmt.Errorf("unable to fetch channel "+
×
727
                                                "edges by channel ID %d: %v",
×
728
                                                chanID, err)
×
729
                        }
×
730

731
                        return info.NodeKey1Bytes, info.NodeKey2Bytes, nil
×
732
                },
733
                FindRoute:              s.chanRouter.FindRoute,
734
                MissionControl:         s.defaultMC,
735
                ActiveNetParams:        r.cfg.ActiveNetParams.Params,
736
                Tower:                  s.controlTower,
737
                MaxTotalTimelock:       r.cfg.MaxOutgoingCltvExpiry,
738
                DefaultFinalCltvDelta:  uint16(r.cfg.Bitcoin.TimeLockDelta),
739
                SubscribeHtlcEvents:    s.htlcNotifier.SubscribeHtlcEvents,
740
                InterceptableForwarder: s.interceptableSwitch,
741
                SetChannelEnabled: func(outpoint wire.OutPoint) error {
3✔
742
                        return s.chanStatusMgr.RequestEnable(outpoint, true)
3✔
743
                },
3✔
744
                SetChannelDisabled: func(outpoint wire.OutPoint) error {
3✔
745
                        return s.chanStatusMgr.RequestDisable(outpoint, true)
3✔
746
                },
3✔
747
                SetChannelAuto:     s.chanStatusMgr.RequestAuto,
748
                UseStatusInitiated: subServerCgs.RouterRPC.UseStatusInitiated,
749
                ParseCustomChannelData: func(msg proto.Message) error {
3✔
750
                        err = fn.MapOptionZ(
3✔
751
                                r.server.implCfg.AuxDataParser,
3✔
752
                                func(parser AuxDataParser) error {
3✔
753
                                        return parser.InlineParseCustomData(msg)
×
754
                                },
×
755
                        )
756
                        if err != nil {
3✔
757
                                return fmt.Errorf("error parsing custom data: "+
×
758
                                        "%w", err)
×
759
                        }
×
760

761
                        return nil
3✔
762
                },
763
                ShouldSetExpEndorsement: func() bool {
3✔
764
                        if s.cfg.ProtocolOptions.NoExperimentalEndorsement() {
3✔
765
                                return false
×
766
                        }
×
767

768
                        return clock.NewDefaultClock().Now().Before(
3✔
769
                                EndorsementExperimentEnd,
3✔
770
                        )
3✔
771
                },
772
        }
773

774
        genInvoiceFeatures := func() *lnwire.FeatureVector {
6✔
775
                return s.featureMgr.Get(feature.SetInvoice)
3✔
776
        }
3✔
777
        genAmpInvoiceFeatures := func() *lnwire.FeatureVector {
3✔
778
                return s.featureMgr.Get(feature.SetInvoiceAmp)
×
779
        }
×
780

781
        parseAddr := func(addr string) (net.Addr, error) {
6✔
782
                return parseAddr(addr, r.cfg.net)
3✔
783
        }
3✔
784

785
        var (
3✔
786
                subServers     []lnrpc.SubServer
3✔
787
                subServerPerms []lnrpc.MacaroonPerms
3✔
788
        )
3✔
789

3✔
790
        // Before we create any of the sub-servers, we need to ensure that all
3✔
791
        // the dependencies they need are properly populated within each sub
3✔
792
        // server configuration struct.
3✔
793
        //
3✔
794
        // TODO(roasbeef): extend sub-sever config to have both (local vs remote) DB
3✔
795
        err = subServerCgs.PopulateDependencies(
3✔
796
                r.cfg, s.cc, r.cfg.networkDir, macService, atpl, invoiceRegistry,
3✔
797
                s.htlcSwitch, r.cfg.ActiveNetParams.Params, s.chanRouter,
3✔
798
                routerBackend, s.nodeSigner, s.graphDB, s.chanStateDB,
3✔
799
                s.sweeper, tower, s.towerClientMgr, r.cfg.net.ResolveTCPAddr,
3✔
800
                genInvoiceFeatures, genAmpInvoiceFeatures,
3✔
801
                s.getNodeAnnouncement, s.updateAndBroadcastSelfNode, parseAddr,
3✔
802
                rpcsLog, s.aliasMgr, r.implCfg.AuxDataParser,
3✔
803
                invoiceHtlcModifier,
3✔
804
        )
3✔
805
        if err != nil {
3✔
806
                return err
×
807
        }
×
808

809
        // Now that the sub-servers have all their dependencies in place, we
810
        // can create each sub-server!
811
        for _, subServerInstance := range r.subGrpcHandlers {
6✔
812
                subServer, macPerms, err := subServerInstance.CreateSubServer(
3✔
813
                        subServerCgs,
3✔
814
                )
3✔
815
                if err != nil {
3✔
816
                        return err
×
817
                }
×
818

819
                // We'll collect the sub-server, and also the set of
820
                // permissions it needs for macaroons so we can apply the
821
                // interceptors below.
822
                subServers = append(subServers, subServer)
3✔
823
                subServerPerms = append(subServerPerms, macPerms)
3✔
824
        }
825

826
        // Next, we need to merge the set of sub server macaroon permissions
827
        // with the main RPC server permissions so we can unite them under a
828
        // single set of interceptors.
829
        for m, ops := range MainRPCServerPermissions() {
6✔
830
                err := r.interceptorChain.AddPermission(m, ops)
3✔
831
                if err != nil {
3✔
832
                        return err
×
833
                }
×
834
        }
835

836
        for _, subServerPerm := range subServerPerms {
6✔
837
                for method, ops := range subServerPerm {
6✔
838
                        err := r.interceptorChain.AddPermission(method, ops)
3✔
839
                        if err != nil {
3✔
840
                                return err
×
841
                        }
×
842
                }
843
        }
844

845
        // External subserver possibly need to register their own permissions
846
        // and macaroon validator.
847
        for method, ops := range r.implCfg.ExternalValidator.Permissions() {
3✔
848
                err := r.interceptorChain.AddPermission(method, ops)
×
849
                if err != nil {
×
850
                        return err
×
851
                }
×
852

853
                // Give the external subservers the possibility to also use
854
                // their own validator to check any macaroons attached to calls
855
                // to this method. This allows them to have their own root key
856
                // ID database and permission entities.
857
                err = macService.RegisterExternalValidator(
×
858
                        method, r.implCfg.ExternalValidator,
×
859
                )
×
860
                if err != nil {
×
861
                        return fmt.Errorf("could not register external "+
×
862
                                "macaroon validator: %v", err)
×
863
                }
×
864
        }
865

866
        // Finally, with all the set up complete, add the last dependencies to
867
        // the rpc server.
868
        r.server = s
3✔
869
        r.subServers = subServers
3✔
870
        r.routerBackend = routerBackend
3✔
871
        r.chanPredicate = chanPredicate
3✔
872
        r.macService = macService
3✔
873
        r.selfNode = selfNode.PubKeyBytes
3✔
874

3✔
875
        graphCacheDuration := r.cfg.Caches.RPCGraphCacheDuration
3✔
876
        if graphCacheDuration != 0 {
6✔
877
                r.graphCacheEvictor = time.AfterFunc(graphCacheDuration, func() {
6✔
878
                        // Grab the mutex and purge the current populated
3✔
879
                        // describe graph response.
3✔
880
                        r.graphCache.Lock()
3✔
881
                        defer r.graphCache.Unlock()
3✔
882

3✔
883
                        r.describeGraphResp = nil
3✔
884

3✔
885
                        // Reset ourselves as well at the end so we run again
3✔
886
                        // after the duration.
3✔
887
                        r.graphCacheEvictor.Reset(graphCacheDuration)
3✔
888
                })
3✔
889
        }
890

891
        return nil
3✔
892
}
893

894
// RegisterWithGrpcServer registers the rpcServer and any subservers with the
895
// root gRPC server.
896
func (r *rpcServer) RegisterWithGrpcServer(grpcServer *grpc.Server) error {
3✔
897
        // Register the main RPC server.
3✔
898
        lnrpc.RegisterLightningServer(grpcServer, r)
3✔
899

3✔
900
        // Now the main RPC server has been registered, we'll iterate through
3✔
901
        // all the sub-RPC servers and register them to ensure that requests
3✔
902
        // are properly routed towards them.
3✔
903
        for _, subServer := range r.subGrpcHandlers {
6✔
904
                err := subServer.RegisterWithRootServer(grpcServer)
3✔
905
                if err != nil {
3✔
906
                        return fmt.Errorf("unable to register "+
×
907
                                "sub-server with root: %v", err)
×
908
                }
×
909
        }
910

911
        // Before actually listening on the gRPC listener, give external
912
        // subservers the chance to register to our gRPC server. Those external
913
        // subservers (think GrUB) are responsible for starting/stopping on
914
        // their own, we just let them register their services to the same
915
        // server instance so all of them can be exposed on the same
916
        // port/listener.
917
        err := r.implCfg.RegisterGrpcSubserver(grpcServer)
3✔
918
        if err != nil {
3✔
919
                rpcsLog.Errorf("error registering external gRPC "+
×
920
                        "subserver: %v", err)
×
921
        }
×
922

923
        return nil
3✔
924
}
925

926
// Start launches any helper goroutines required for the rpcServer to function.
927
func (r *rpcServer) Start() error {
3✔
928
        if atomic.AddInt32(&r.started, 1) != 1 {
3✔
929
                return nil
×
930
        }
×
931

932
        // First, we'll start all the sub-servers to ensure that they're ready
933
        // to take new requests in.
934
        //
935
        // TODO(roasbeef): some may require that the entire daemon be started
936
        // at that point
937
        for _, subServer := range r.subServers {
6✔
938
                rpcsLog.Debugf("Starting sub RPC server: %v", subServer.Name())
3✔
939

3✔
940
                if err := subServer.Start(); err != nil {
3✔
941
                        return err
×
942
                }
×
943
        }
944

945
        return nil
3✔
946
}
947

948
// RegisterWithRestProxy registers the RPC server and any subservers with the
949
// given REST proxy.
950
func (r *rpcServer) RegisterWithRestProxy(restCtx context.Context,
951
        restMux *proxy.ServeMux, restDialOpts []grpc.DialOption,
952
        restProxyDest string) error {
3✔
953

3✔
954
        // With our custom REST proxy mux created, register our main RPC and
3✔
955
        // give all subservers a chance to register as well.
3✔
956
        err := lnrpc.RegisterLightningHandlerFromEndpoint(
3✔
957
                restCtx, restMux, restProxyDest, restDialOpts,
3✔
958
        )
3✔
959
        if err != nil {
3✔
960
                return err
×
961
        }
×
962

963
        // Register our State service with the REST proxy.
964
        err = lnrpc.RegisterStateHandlerFromEndpoint(
3✔
965
                restCtx, restMux, restProxyDest, restDialOpts,
3✔
966
        )
3✔
967
        if err != nil {
3✔
968
                return err
×
969
        }
×
970

971
        // Register all the subservers with the REST proxy.
972
        for _, subServer := range r.subGrpcHandlers {
6✔
973
                err := subServer.RegisterWithRestServer(
3✔
974
                        restCtx, restMux, restProxyDest, restDialOpts,
3✔
975
                )
3✔
976
                if err != nil {
3✔
977
                        return fmt.Errorf("unable to register REST sub-server "+
×
978
                                "with root: %v", err)
×
979
                }
×
980
        }
981

982
        // Before listening on any of the interfaces, we also want to give the
983
        // external subservers a chance to register their own REST proxy stub
984
        // with our mux instance.
985
        err = r.implCfg.RegisterRestSubserver(
3✔
986
                restCtx, restMux, restProxyDest, restDialOpts,
3✔
987
        )
3✔
988
        if err != nil {
3✔
989
                rpcsLog.Errorf("error registering external REST subserver: %v",
×
990
                        err)
×
991
        }
×
992
        return nil
3✔
993
}
994

995
// Stop signals any active goroutines for a graceful closure.
996
func (r *rpcServer) Stop() error {
3✔
997
        if atomic.AddInt32(&r.shutdown, 1) != 1 {
3✔
998
                return nil
×
999
        }
×
1000

1001
        rpcsLog.Infof("Stopping RPC Server")
3✔
1002

3✔
1003
        close(r.quit)
3✔
1004

3✔
1005
        // After we've signalled all of our active goroutines to exit, we'll
3✔
1006
        // then do the same to signal a graceful shutdown of all the sub
3✔
1007
        // servers.
3✔
1008
        for _, subServer := range r.subServers {
6✔
1009
                rpcsLog.Infof("Stopping %v Sub-RPC Server",
3✔
1010
                        subServer.Name())
3✔
1011

3✔
1012
                if err := subServer.Stop(); err != nil {
3✔
1013
                        rpcsLog.Errorf("unable to stop sub-server %v: %v",
×
1014
                                subServer.Name(), err)
×
1015
                        continue
×
1016
                }
1017
        }
1018

1019
        return nil
3✔
1020
}
1021

1022
// addrPairsToOutputs converts a map describing a set of outputs to be created,
1023
// the outputs themselves. The passed map pairs up an address, to a desired
1024
// output value amount. Each address is converted to its corresponding pkScript
1025
// to be used within the constructed output(s).
1026
func addrPairsToOutputs(addrPairs map[string]int64,
1027
        params *chaincfg.Params) ([]*wire.TxOut, error) {
3✔
1028

3✔
1029
        outputs := make([]*wire.TxOut, 0, len(addrPairs))
3✔
1030
        for addr, amt := range addrPairs {
6✔
1031
                addr, err := btcutil.DecodeAddress(addr, params)
3✔
1032
                if err != nil {
3✔
1033
                        return nil, err
×
1034
                }
×
1035

1036
                if !addr.IsForNet(params) {
3✔
1037
                        return nil, fmt.Errorf("address is not for %s",
×
1038
                                params.Name)
×
1039
                }
×
1040

1041
                pkscript, err := txscript.PayToAddrScript(addr)
3✔
1042
                if err != nil {
3✔
1043
                        return nil, err
×
1044
                }
×
1045

1046
                outputs = append(outputs, wire.NewTxOut(amt, pkscript))
3✔
1047
        }
1048

1049
        return outputs, nil
3✔
1050
}
1051

1052
// allowCORS wraps the given http.Handler with a function that adds the
1053
// Access-Control-Allow-Origin header to the response.
1054
func allowCORS(handler http.Handler, origins []string) http.Handler {
3✔
1055
        allowHeaders := "Access-Control-Allow-Headers"
3✔
1056
        allowMethods := "Access-Control-Allow-Methods"
3✔
1057
        allowOrigin := "Access-Control-Allow-Origin"
3✔
1058

3✔
1059
        // If the user didn't supply any origins that means CORS is disabled
3✔
1060
        // and we should return the original handler.
3✔
1061
        if len(origins) == 0 {
3✔
1062
                return handler
×
1063
        }
×
1064

1065
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
6✔
1066
                origin := r.Header.Get("Origin")
3✔
1067

3✔
1068
                // Skip everything if the browser doesn't send the Origin field.
3✔
1069
                if origin == "" {
6✔
1070
                        handler.ServeHTTP(w, r)
3✔
1071
                        return
3✔
1072
                }
3✔
1073

1074
                // Set the static header fields first.
1075
                w.Header().Set(
3✔
1076
                        allowHeaders,
3✔
1077
                        "Content-Type, Accept, Grpc-Metadata-Macaroon",
3✔
1078
                )
3✔
1079
                w.Header().Set(allowMethods, "GET, POST, DELETE")
3✔
1080

3✔
1081
                // Either we allow all origins or the incoming request matches
3✔
1082
                // a specific origin in our list of allowed origins.
3✔
1083
                for _, allowedOrigin := range origins {
6✔
1084
                        if allowedOrigin == "*" || origin == allowedOrigin {
6✔
1085
                                // Only set allowed origin to requested origin.
3✔
1086
                                w.Header().Set(allowOrigin, origin)
3✔
1087

3✔
1088
                                break
3✔
1089
                        }
1090
                }
1091

1092
                // For a pre-flight request we only need to send the headers
1093
                // back. No need to call the rest of the chain.
1094
                if r.Method == "OPTIONS" {
6✔
1095
                        return
3✔
1096
                }
3✔
1097

1098
                // Everything's prepared now, we can pass the request along the
1099
                // chain of handlers.
1100
                handler.ServeHTTP(w, r)
×
1101
        })
1102
}
1103

1104
// sendCoinsOnChain makes an on-chain transaction in or to send coins to one or
1105
// more addresses specified in the passed payment map. The payment map maps an
1106
// address to a specified output value to be sent to that address.
1107
func (r *rpcServer) sendCoinsOnChain(paymentMap map[string]int64,
1108
        feeRate chainfee.SatPerKWeight, minConfs int32, label string,
1109
        strategy wallet.CoinSelectionStrategy,
1110
        selectedUtxos fn.Set[wire.OutPoint]) (*chainhash.Hash, error) {
3✔
1111

3✔
1112
        outputs, err := addrPairsToOutputs(paymentMap, r.cfg.ActiveNetParams.Params)
3✔
1113
        if err != nil {
3✔
1114
                return nil, err
×
1115
        }
×
1116

1117
        // We first do a dry run, to sanity check we won't spend our wallet
1118
        // balance below the reserved amount.
1119
        authoredTx, err := r.server.cc.Wallet.CreateSimpleTx(
3✔
1120
                selectedUtxos, outputs, feeRate, minConfs, strategy, true,
3✔
1121
        )
3✔
1122
        if err != nil {
6✔
1123
                return nil, err
3✔
1124
        }
3✔
1125

1126
        // Check the authored transaction and use the explicitly set change index
1127
        // to make sure that the wallet reserved balance is not invalidated.
1128
        _, err = r.server.cc.Wallet.CheckReservedValueTx(
3✔
1129
                lnwallet.CheckReservedValueTxReq{
3✔
1130
                        Tx:          authoredTx.Tx,
3✔
1131
                        ChangeIndex: &authoredTx.ChangeIndex,
3✔
1132
                },
3✔
1133
        )
3✔
1134
        if err != nil {
6✔
1135
                return nil, err
3✔
1136
        }
3✔
1137

1138
        // If that checks out, we're fairly confident that creating sending to
1139
        // these outputs will keep the wallet balance above the reserve.
1140
        tx, err := r.server.cc.Wallet.SendOutputs(
3✔
1141
                selectedUtxos, outputs, feeRate, minConfs, label, strategy,
3✔
1142
        )
3✔
1143
        if err != nil {
3✔
1144
                return nil, err
×
1145
        }
×
1146

1147
        txHash := tx.TxHash()
3✔
1148
        return &txHash, nil
3✔
1149
}
1150

1151
// ListUnspent returns useful information about each unspent output owned by
1152
// the wallet, as reported by the underlying `ListUnspentWitness`; the
1153
// information returned is: outpoint, amount in satoshis, address, address
1154
// type, scriptPubKey in hex and number of confirmations.  The result is
1155
// filtered to contain outputs whose number of confirmations is between a
1156
// minimum and maximum number of confirmations specified by the user, with
1157
// 0 meaning unconfirmed.
1158
func (r *rpcServer) ListUnspent(ctx context.Context,
1159
        in *lnrpc.ListUnspentRequest) (*lnrpc.ListUnspentResponse, error) {
×
1160

×
1161
        // Validate the confirmation arguments.
×
1162
        minConfs, maxConfs, err := lnrpc.ParseConfs(in.MinConfs, in.MaxConfs)
×
1163
        if err != nil {
×
1164
                return nil, err
×
1165
        }
×
1166

1167
        // With our arguments validated, we'll query the internal wallet for
1168
        // the set of UTXOs that match our query.
1169
        //
1170
        // We'll acquire the global coin selection lock to ensure there aren't
1171
        // any other concurrent processes attempting to lock any UTXOs which may
1172
        // be shown available to us.
1173
        var utxos []*lnwallet.Utxo
×
1174
        err = r.server.cc.Wallet.WithCoinSelectLock(func() error {
×
1175
                utxos, err = r.server.cc.Wallet.ListUnspentWitness(
×
1176
                        minConfs, maxConfs, in.Account,
×
1177
                )
×
1178
                return err
×
1179
        })
×
1180
        if err != nil {
×
1181
                return nil, err
×
1182
        }
×
1183

1184
        rpcUtxos, err := lnrpc.MarshalUtxos(utxos, r.cfg.ActiveNetParams.Params)
×
1185
        if err != nil {
×
1186
                return nil, err
×
1187
        }
×
1188

1189
        maxStr := ""
×
1190
        if maxConfs != math.MaxInt32 {
×
1191
                maxStr = " max=" + fmt.Sprintf("%d", maxConfs)
×
1192
        }
×
1193

1194
        rpcsLog.Debugf("[listunspent] min=%v%v, generated utxos: %v", minConfs,
×
1195
                maxStr, utxos)
×
1196

×
1197
        return &lnrpc.ListUnspentResponse{
×
1198
                Utxos: rpcUtxos,
×
1199
        }, nil
×
1200
}
1201

1202
// EstimateFee handles a request for estimating the fee for sending a
1203
// transaction spending to multiple specified outputs in parallel.
1204
func (r *rpcServer) EstimateFee(ctx context.Context,
1205
        in *lnrpc.EstimateFeeRequest) (*lnrpc.EstimateFeeResponse, error) {
3✔
1206

3✔
1207
        // Create the list of outputs we are spending to.
3✔
1208
        outputs, err := addrPairsToOutputs(in.AddrToAmount, r.cfg.ActiveNetParams.Params)
3✔
1209
        if err != nil {
3✔
1210
                return nil, err
×
1211
        }
×
1212

1213
        // Query the fee estimator for the fee rate for the given confirmation
1214
        // target.
1215
        target := in.TargetConf
3✔
1216
        feePref := sweep.FeeEstimateInfo{
3✔
1217
                ConfTarget: uint32(target),
3✔
1218
        }
3✔
1219

3✔
1220
        // Since we are providing a fee estimation as an RPC response, there's
3✔
1221
        // no need to set a max feerate here, so we use 0.
3✔
1222
        feePerKw, err := feePref.Estimate(r.server.cc.FeeEstimator, 0)
3✔
1223
        if err != nil {
3✔
1224
                return nil, err
×
1225
        }
×
1226

1227
        // Then, we'll extract the minimum number of confirmations that each
1228
        // output we use to fund the transaction should satisfy.
1229
        minConfs, err := lnrpc.ExtractMinConfs(
3✔
1230
                in.GetMinConfs(), in.GetSpendUnconfirmed(),
3✔
1231
        )
3✔
1232
        if err != nil {
3✔
1233
                return nil, err
×
1234
        }
×
1235

1236
        coinSelectionStrategy, err := lnrpc.UnmarshallCoinSelectionStrategy(
3✔
1237
                in.CoinSelectionStrategy,
3✔
1238
                r.server.cc.Wallet.Cfg.CoinSelectionStrategy,
3✔
1239
        )
3✔
1240
        if err != nil {
3✔
1241
                return nil, err
×
1242
        }
×
1243

1244
        // We will ask the wallet to create a tx using this fee rate. We set
1245
        // dryRun=true to avoid inflating the change addresses in the db.
1246
        var tx *txauthor.AuthoredTx
3✔
1247
        wallet := r.server.cc.Wallet
3✔
1248
        err = wallet.WithCoinSelectLock(func() error {
6✔
1249
                tx, err = wallet.CreateSimpleTx(
3✔
1250
                        nil, outputs, feePerKw, minConfs, coinSelectionStrategy,
3✔
1251
                        true,
3✔
1252
                )
3✔
1253
                return err
3✔
1254
        })
3✔
1255
        if err != nil {
3✔
1256
                return nil, err
×
1257
        }
×
1258

1259
        // Use the created tx to calculate the total fee.
1260
        totalOutput := int64(0)
3✔
1261
        for _, out := range tx.Tx.TxOut {
6✔
1262
                totalOutput += out.Value
3✔
1263
        }
3✔
1264
        totalFee := int64(tx.TotalInput) - totalOutput
3✔
1265

3✔
1266
        resp := &lnrpc.EstimateFeeResponse{
3✔
1267
                FeeSat:      totalFee,
3✔
1268
                SatPerVbyte: uint64(feePerKw.FeePerVByte()),
3✔
1269

3✔
1270
                // Deprecated field.
3✔
1271
                FeerateSatPerByte: int64(feePerKw.FeePerVByte()),
3✔
1272
        }
3✔
1273

3✔
1274
        rpcsLog.Debugf("[estimatefee] fee estimate for conf target %d: %v",
3✔
1275
                target, resp)
3✔
1276

3✔
1277
        return resp, nil
3✔
1278
}
1279

1280
// maybeUseDefaultConf makes sure that when the user doesn't set either the fee
1281
// rate or conf target, the default conf target is used.
1282
func maybeUseDefaultConf(satPerByte int64, satPerVByte uint64,
1283
        targetConf uint32) uint32 {
3✔
1284

3✔
1285
        // If the fee rate is set, there's no need to use the default conf
3✔
1286
        // target. In this case, we just return the targetConf from the
3✔
1287
        // request.
3✔
1288
        if satPerByte != 0 || satPerVByte != 0 {
6✔
1289
                return targetConf
3✔
1290
        }
3✔
1291

1292
        // Return the user specified conf target if set.
1293
        if targetConf != 0 {
6✔
1294
                return targetConf
3✔
1295
        }
3✔
1296

1297
        // If the fee rate is not set, yet the conf target is zero, the default
1298
        // 6 will be returned.
1299
        rpcsLog.Errorf("Expected either 'sat_per_vbyte' or 'conf_target' to " +
3✔
1300
                "be set, using default conf of 6 instead")
3✔
1301

3✔
1302
        return defaultNumBlocksEstimate
3✔
1303
}
1304

1305
// SendCoins executes a request to send coins to a particular address. Unlike
1306
// SendMany, this RPC call only allows creating a single output at a time.
1307
func (r *rpcServer) SendCoins(ctx context.Context,
1308
        in *lnrpc.SendCoinsRequest) (*lnrpc.SendCoinsResponse, error) {
3✔
1309

3✔
1310
        // Keep the old behavior prior to 0.18.0 - when the user doesn't set
3✔
1311
        // fee rate or conf target, the default conf target of 6 is used.
3✔
1312
        targetConf := maybeUseDefaultConf(
3✔
1313
                in.SatPerByte, in.SatPerVbyte, uint32(in.TargetConf),
3✔
1314
        )
3✔
1315

3✔
1316
        // Calculate an appropriate fee rate for this transaction.
3✔
1317
        feePerKw, err := lnrpc.CalculateFeeRate(
3✔
1318
                uint64(in.SatPerByte), in.SatPerVbyte, // nolint:staticcheck
3✔
1319
                targetConf, r.server.cc.FeeEstimator,
3✔
1320
        )
3✔
1321
        if err != nil {
3✔
1322
                return nil, err
×
1323
        }
×
1324

1325
        // Then, we'll extract the minimum number of confirmations that each
1326
        // output we use to fund the transaction should satisfy.
1327
        minConfs, err := lnrpc.ExtractMinConfs(in.MinConfs, in.SpendUnconfirmed)
3✔
1328
        if err != nil {
3✔
1329
                return nil, err
×
1330
        }
×
1331

1332
        rpcsLog.Infof("[sendcoins] addr=%v, amt=%v, sat/kw=%v, min_confs=%v, "+
3✔
1333
                "send_all=%v, select_outpoints=%v",
3✔
1334
                in.Addr, btcutil.Amount(in.Amount), int64(feePerKw), minConfs,
3✔
1335
                in.SendAll, len(in.Outpoints))
3✔
1336

3✔
1337
        // Decode the address receiving the coins, we need to check whether the
3✔
1338
        // address is valid for this network.
3✔
1339
        targetAddr, err := btcutil.DecodeAddress(
3✔
1340
                in.Addr, r.cfg.ActiveNetParams.Params,
3✔
1341
        )
3✔
1342
        if err != nil {
6✔
1343
                return nil, err
3✔
1344
        }
3✔
1345

1346
        // Make the check on the decoded address according to the active network.
1347
        if !targetAddr.IsForNet(r.cfg.ActiveNetParams.Params) {
6✔
1348
                return nil, fmt.Errorf("address: %v is not valid for this "+
3✔
1349
                        "network: %v", targetAddr.String(),
3✔
1350
                        r.cfg.ActiveNetParams.Params.Name)
3✔
1351
        }
3✔
1352

1353
        // If the destination address parses to a valid pubkey, we assume the user
1354
        // accidentally tried to send funds to a bare pubkey address. This check is
1355
        // here to prevent unintended transfers.
1356
        decodedAddr, _ := hex.DecodeString(in.Addr)
3✔
1357
        _, err = btcec.ParsePubKey(decodedAddr)
3✔
1358
        if err == nil {
6✔
1359
                return nil, fmt.Errorf("cannot send coins to pubkeys")
3✔
1360
        }
3✔
1361

1362
        label, err := labels.ValidateAPI(in.Label)
3✔
1363
        if err != nil {
3✔
1364
                return nil, err
×
1365
        }
×
1366

1367
        coinSelectionStrategy, err := lnrpc.UnmarshallCoinSelectionStrategy(
3✔
1368
                in.CoinSelectionStrategy,
3✔
1369
                r.server.cc.Wallet.Cfg.CoinSelectionStrategy,
3✔
1370
        )
3✔
1371
        if err != nil {
3✔
1372
                return nil, err
×
1373
        }
×
1374

1375
        var txid *chainhash.Hash
3✔
1376

3✔
1377
        wallet := r.server.cc.Wallet
3✔
1378
        maxFeeRate := r.cfg.Sweeper.MaxFeeRate.FeePerKWeight()
3✔
1379

3✔
1380
        var selectOutpoints fn.Set[wire.OutPoint]
3✔
1381
        if len(in.Outpoints) != 0 {
6✔
1382
                wireOutpoints, err := toWireOutpoints(in.Outpoints)
3✔
1383
                if err != nil {
3✔
1384
                        return nil, fmt.Errorf("can't create outpoints "+
×
1385
                                "%w", err)
×
1386
                }
×
1387

1388
                if fn.HasDuplicates(wireOutpoints) {
6✔
1389
                        return nil, fmt.Errorf("selected outpoints contain " +
3✔
1390
                                "duplicate values")
3✔
1391
                }
3✔
1392

1393
                selectOutpoints = fn.NewSet(wireOutpoints...)
3✔
1394
        }
1395

1396
        // If the send all flag is active, then we'll attempt to sweep all the
1397
        // coins in the wallet in a single transaction (if possible),
1398
        // otherwise, we'll respect the amount, and attempt a regular 2-output
1399
        // send.
1400
        if in.SendAll {
6✔
1401
                // At this point, the amount shouldn't be set since we've been
3✔
1402
                // instructed to sweep all the coins from the wallet.
3✔
1403
                if in.Amount != 0 {
6✔
1404
                        return nil, fmt.Errorf("amount set while SendAll is " +
3✔
1405
                                "active")
3✔
1406
                }
3✔
1407

1408
                _, bestHeight, err := r.server.cc.ChainIO.GetBestBlock()
3✔
1409
                if err != nil {
3✔
1410
                        return nil, err
×
1411
                }
×
1412

1413
                // With the sweeper instance created, we can now generate a
1414
                // transaction that will sweep ALL outputs from the wallet in a
1415
                // single transaction. This will be generated in a concurrent
1416
                // safe manner, so no need to worry about locking. The tx will
1417
                // pay to the change address created above if we needed to
1418
                // reserve any value, the rest will go to targetAddr.
1419
                sweepTxPkg, err := sweep.CraftSweepAllTx(
3✔
1420
                        feePerKw, maxFeeRate, uint32(bestHeight), nil,
3✔
1421
                        targetAddr, wallet, wallet, wallet.WalletController,
3✔
1422
                        r.server.cc.Signer, minConfs, selectOutpoints,
3✔
1423
                )
3✔
1424
                if err != nil {
3✔
1425
                        return nil, err
×
1426
                }
×
1427

1428
                // Before we publish the transaction we make sure it won't
1429
                // violate our reserved wallet value.
1430
                var reservedVal btcutil.Amount
3✔
1431
                err = wallet.WithCoinSelectLock(func() error {
6✔
1432
                        var err error
3✔
1433
                        reservedVal, err = wallet.CheckReservedValueTx(
3✔
1434
                                lnwallet.CheckReservedValueTxReq{
3✔
1435
                                        Tx: sweepTxPkg.SweepTx,
3✔
1436
                                },
3✔
1437
                        )
3✔
1438
                        return err
3✔
1439
                })
3✔
1440

1441
                // If sending everything to this address would invalidate our
1442
                // reserved wallet balance, we create a new sweep tx, where
1443
                // we'll send the reserved value back to our wallet.
1444
                if err == lnwallet.ErrReservedValueInvalidated {
6✔
1445
                        sweepTxPkg.CancelSweepAttempt()
3✔
1446

3✔
1447
                        rpcsLog.Debugf("Reserved value %v not satisfied after "+
3✔
1448
                                "send_all, trying with change output",
3✔
1449
                                reservedVal)
3✔
1450

3✔
1451
                        // We'll request a change address from the wallet,
3✔
1452
                        // where we'll send this reserved value back to. This
3✔
1453
                        // ensures this is an address the wallet knows about,
3✔
1454
                        // allowing us to pass the reserved value check.
3✔
1455
                        changeAddr, err := r.server.cc.Wallet.NewAddress(
3✔
1456
                                lnwallet.TaprootPubkey, true,
3✔
1457
                                lnwallet.DefaultAccountName,
3✔
1458
                        )
3✔
1459
                        if err != nil {
3✔
1460
                                return nil, err
×
1461
                        }
×
1462

1463
                        // Send the reserved value to this change address, the
1464
                        // remaining funds will go to the targetAddr.
1465
                        outputs := []sweep.DeliveryAddr{
3✔
1466
                                {
3✔
1467
                                        Addr: changeAddr,
3✔
1468
                                        Amt:  reservedVal,
3✔
1469
                                },
3✔
1470
                        }
3✔
1471

3✔
1472
                        sweepTxPkg, err = sweep.CraftSweepAllTx(
3✔
1473
                                feePerKw, maxFeeRate, uint32(bestHeight),
3✔
1474
                                outputs, targetAddr, wallet, wallet,
3✔
1475
                                wallet.WalletController,
3✔
1476
                                r.server.cc.Signer, minConfs, selectOutpoints,
3✔
1477
                        )
3✔
1478
                        if err != nil {
3✔
1479
                                return nil, err
×
1480
                        }
×
1481

1482
                        // Sanity check the new tx by re-doing the check.
1483
                        err = wallet.WithCoinSelectLock(func() error {
6✔
1484
                                _, err := wallet.CheckReservedValueTx(
3✔
1485
                                        lnwallet.CheckReservedValueTxReq{
3✔
1486
                                                Tx: sweepTxPkg.SweepTx,
3✔
1487
                                        },
3✔
1488
                                )
3✔
1489
                                return err
3✔
1490
                        })
3✔
1491
                        if err != nil {
3✔
1492
                                sweepTxPkg.CancelSweepAttempt()
×
1493

×
1494
                                return nil, err
×
1495
                        }
×
1496
                } else if err != nil {
3✔
1497
                        sweepTxPkg.CancelSweepAttempt()
×
1498

×
1499
                        return nil, err
×
1500
                }
×
1501

1502
                rpcsLog.Debugf("Sweeping coins from wallet to addr=%v, "+
3✔
1503
                        "with tx=%v", in.Addr, spew.Sdump(sweepTxPkg.SweepTx))
3✔
1504

3✔
1505
                // As our sweep transaction was created, successfully, we'll
3✔
1506
                // now attempt to publish it, cancelling the sweep pkg to
3✔
1507
                // return all outputs if it fails.
3✔
1508
                err = wallet.PublishTransaction(sweepTxPkg.SweepTx, label)
3✔
1509
                if err != nil {
3✔
1510
                        sweepTxPkg.CancelSweepAttempt()
×
1511

×
1512
                        return nil, fmt.Errorf("unable to broadcast sweep "+
×
1513
                                "transaction: %v", err)
×
1514
                }
×
1515

1516
                sweepTXID := sweepTxPkg.SweepTx.TxHash()
3✔
1517
                txid = &sweepTXID
3✔
1518
        } else {
3✔
1519

3✔
1520
                // We'll now construct out payment map, and use the wallet's
3✔
1521
                // coin selection synchronization method to ensure that no coin
3✔
1522
                // selection (funding, sweep alls, other sends) can proceed
3✔
1523
                // while we instruct the wallet to send this transaction.
3✔
1524
                paymentMap := map[string]int64{targetAddr.String(): in.Amount}
3✔
1525
                err := wallet.WithCoinSelectLock(func() error {
6✔
1526
                        newTXID, err := r.sendCoinsOnChain(
3✔
1527
                                paymentMap, feePerKw, minConfs, label,
3✔
1528
                                coinSelectionStrategy, selectOutpoints,
3✔
1529
                        )
3✔
1530
                        if err != nil {
6✔
1531
                                return err
3✔
1532
                        }
3✔
1533

1534
                        txid = newTXID
3✔
1535

3✔
1536
                        return nil
3✔
1537
                })
1538
                if err != nil {
6✔
1539
                        return nil, err
3✔
1540
                }
3✔
1541
        }
1542

1543
        rpcsLog.Infof("[sendcoins] spend generated txid: %v", txid.String())
3✔
1544

3✔
1545
        return &lnrpc.SendCoinsResponse{Txid: txid.String()}, nil
3✔
1546
}
1547

1548
// SendMany handles a request for a transaction create multiple specified
1549
// outputs in parallel.
1550
func (r *rpcServer) SendMany(ctx context.Context,
1551
        in *lnrpc.SendManyRequest) (*lnrpc.SendManyResponse, error) {
×
1552

×
1553
        // Keep the old behavior prior to 0.18.0 - when the user doesn't set
×
1554
        // fee rate or conf target, the default conf target of 6 is used.
×
1555
        targetConf := maybeUseDefaultConf(
×
1556
                in.SatPerByte, in.SatPerVbyte, uint32(in.TargetConf),
×
1557
        )
×
1558

×
1559
        // Calculate an appropriate fee rate for this transaction.
×
1560
        feePerKw, err := lnrpc.CalculateFeeRate(
×
1561
                uint64(in.SatPerByte), in.SatPerVbyte, // nolint:staticcheck
×
1562
                targetConf, r.server.cc.FeeEstimator,
×
1563
        )
×
1564
        if err != nil {
×
1565
                return nil, err
×
1566
        }
×
1567

1568
        // Then, we'll extract the minimum number of confirmations that each
1569
        // output we use to fund the transaction should satisfy.
1570
        minConfs, err := lnrpc.ExtractMinConfs(in.MinConfs, in.SpendUnconfirmed)
×
1571
        if err != nil {
×
1572
                return nil, err
×
1573
        }
×
1574

1575
        label, err := labels.ValidateAPI(in.Label)
×
1576
        if err != nil {
×
1577
                return nil, err
×
1578
        }
×
1579

1580
        coinSelectionStrategy, err := lnrpc.UnmarshallCoinSelectionStrategy(
×
1581
                in.CoinSelectionStrategy,
×
1582
                r.server.cc.Wallet.Cfg.CoinSelectionStrategy,
×
1583
        )
×
1584
        if err != nil {
×
1585
                return nil, err
×
1586
        }
×
1587

1588
        rpcsLog.Infof("[sendmany] outputs=%v, sat/kw=%v",
×
1589
                spew.Sdump(in.AddrToAmount), int64(feePerKw))
×
1590

×
1591
        var txid *chainhash.Hash
×
1592

×
1593
        // We'll attempt to send to the target set of outputs, ensuring that we
×
1594
        // synchronize with any other ongoing coin selection attempts which
×
1595
        // happen to also be concurrently executing.
×
1596
        wallet := r.server.cc.Wallet
×
1597
        err = wallet.WithCoinSelectLock(func() error {
×
1598
                sendManyTXID, err := r.sendCoinsOnChain(
×
1599
                        in.AddrToAmount, feePerKw, minConfs, label,
×
1600
                        coinSelectionStrategy, nil,
×
1601
                )
×
1602
                if err != nil {
×
1603
                        return err
×
1604
                }
×
1605

1606
                txid = sendManyTXID
×
1607

×
1608
                return nil
×
1609
        })
1610
        if err != nil {
×
1611
                return nil, err
×
1612
        }
×
1613

1614
        rpcsLog.Infof("[sendmany] spend generated txid: %v", txid.String())
×
1615

×
1616
        return &lnrpc.SendManyResponse{Txid: txid.String()}, nil
×
1617
}
1618

1619
// NewAddress creates a new address under control of the local wallet.
1620
func (r *rpcServer) NewAddress(ctx context.Context,
1621
        in *lnrpc.NewAddressRequest) (*lnrpc.NewAddressResponse, error) {
3✔
1622

3✔
1623
        // Always use the default wallet account unless one was specified.
3✔
1624
        account := lnwallet.DefaultAccountName
3✔
1625
        if in.Account != "" {
6✔
1626
                account = in.Account
3✔
1627
        }
3✔
1628

1629
        // Translate the gRPC proto address type to the wallet controller's
1630
        // available address types.
1631
        var (
3✔
1632
                addr btcutil.Address
3✔
1633
                err  error
3✔
1634
        )
3✔
1635
        switch in.Type {
3✔
1636
        case lnrpc.AddressType_WITNESS_PUBKEY_HASH:
3✔
1637
                addr, err = r.server.cc.Wallet.NewAddress(
3✔
1638
                        lnwallet.WitnessPubKey, false, account,
3✔
1639
                )
3✔
1640
                if err != nil {
3✔
1641
                        return nil, err
×
1642
                }
×
1643

1644
        case lnrpc.AddressType_NESTED_PUBKEY_HASH:
3✔
1645
                addr, err = r.server.cc.Wallet.NewAddress(
3✔
1646
                        lnwallet.NestedWitnessPubKey, false, account,
3✔
1647
                )
3✔
1648
                if err != nil {
3✔
1649
                        return nil, err
×
1650
                }
×
1651

1652
        case lnrpc.AddressType_TAPROOT_PUBKEY:
3✔
1653
                addr, err = r.server.cc.Wallet.NewAddress(
3✔
1654
                        lnwallet.TaprootPubkey, false, account,
3✔
1655
                )
3✔
1656
                if err != nil {
3✔
1657
                        return nil, err
×
1658
                }
×
1659

1660
        case lnrpc.AddressType_UNUSED_WITNESS_PUBKEY_HASH:
3✔
1661
                addr, err = r.server.cc.Wallet.LastUnusedAddress(
3✔
1662
                        lnwallet.WitnessPubKey, account,
3✔
1663
                )
3✔
1664
                if err != nil {
3✔
1665
                        return nil, err
×
1666
                }
×
1667

1668
        case lnrpc.AddressType_UNUSED_NESTED_PUBKEY_HASH:
×
1669
                addr, err = r.server.cc.Wallet.LastUnusedAddress(
×
1670
                        lnwallet.NestedWitnessPubKey, account,
×
1671
                )
×
1672
                if err != nil {
×
1673
                        return nil, err
×
1674
                }
×
1675

1676
        case lnrpc.AddressType_UNUSED_TAPROOT_PUBKEY:
3✔
1677
                addr, err = r.server.cc.Wallet.LastUnusedAddress(
3✔
1678
                        lnwallet.TaprootPubkey, account,
3✔
1679
                )
3✔
1680
                if err != nil {
3✔
1681
                        return nil, err
×
1682
                }
×
1683

1684
        default:
×
1685
                return nil, fmt.Errorf("unknown address type: %v", in.Type)
×
1686
        }
1687

1688
        rpcsLog.Debugf("[newaddress] account=%v type=%v addr=%v", account,
3✔
1689
                in.Type, addr.String())
3✔
1690
        return &lnrpc.NewAddressResponse{Address: addr.String()}, nil
3✔
1691
}
1692

1693
var (
1694
        // signedMsgPrefix is a special prefix that we'll prepend to any
1695
        // messages we sign/verify. We do this to ensure that we don't
1696
        // accidentally sign a sighash, or other sensitive material. By
1697
        // prepending this fragment, we mind message signing to our particular
1698
        // context.
1699
        signedMsgPrefix = []byte("Lightning Signed Message:")
1700
)
1701

1702
// SignMessage signs a message with the resident node's private key. The
1703
// returned signature string is zbase32 encoded and pubkey recoverable, meaning
1704
// that only the message digest and signature are needed for verification.
1705
func (r *rpcServer) SignMessage(_ context.Context,
1706
        in *lnrpc.SignMessageRequest) (*lnrpc.SignMessageResponse, error) {
3✔
1707

3✔
1708
        if in.Msg == nil {
3✔
1709
                return nil, fmt.Errorf("need a message to sign")
×
1710
        }
×
1711

1712
        in.Msg = append(signedMsgPrefix, in.Msg...)
3✔
1713
        sigBytes, err := r.server.nodeSigner.SignMessageCompact(
3✔
1714
                in.Msg, !in.SingleHash,
3✔
1715
        )
3✔
1716
        if err != nil {
3✔
1717
                return nil, err
×
1718
        }
×
1719

1720
        sig := zbase32.EncodeToString(sigBytes)
3✔
1721
        return &lnrpc.SignMessageResponse{Signature: sig}, nil
3✔
1722
}
1723

1724
// VerifyMessage verifies a signature over a msg. The signature must be zbase32
1725
// encoded and signed by an active node in the resident node's channel
1726
// database. In addition to returning the validity of the signature,
1727
// VerifyMessage also returns the recovered pubkey from the signature.
1728
func (r *rpcServer) VerifyMessage(ctx context.Context,
1729
        in *lnrpc.VerifyMessageRequest) (*lnrpc.VerifyMessageResponse, error) {
3✔
1730

3✔
1731
        if in.Msg == nil {
3✔
1732
                return nil, fmt.Errorf("need a message to verify")
×
1733
        }
×
1734

1735
        // The signature should be zbase32 encoded
1736
        sig, err := zbase32.DecodeString(in.Signature)
3✔
1737
        if err != nil {
3✔
1738
                return nil, fmt.Errorf("failed to decode signature: %w", err)
×
1739
        }
×
1740

1741
        // The signature is over the double-sha256 hash of the message.
1742
        in.Msg = append(signedMsgPrefix, in.Msg...)
3✔
1743
        digest := chainhash.DoubleHashB(in.Msg)
3✔
1744

3✔
1745
        // RecoverCompact both recovers the pubkey and validates the signature.
3✔
1746
        pubKey, _, err := ecdsa.RecoverCompact(sig, digest)
3✔
1747
        if err != nil {
3✔
1748
                return &lnrpc.VerifyMessageResponse{Valid: false}, nil
×
1749
        }
×
1750
        pubKeyHex := hex.EncodeToString(pubKey.SerializeCompressed())
3✔
1751

3✔
1752
        var pub [33]byte
3✔
1753
        copy(pub[:], pubKey.SerializeCompressed())
3✔
1754

3✔
1755
        // Query the channel graph to ensure a node in the network with active
3✔
1756
        // channels signed the message.
3✔
1757
        //
3✔
1758
        // TODO(phlip9): Require valid nodes to have capital in active channels.
3✔
1759
        graph := r.server.graphDB
3✔
1760
        _, active, err := graph.HasLightningNode(pub)
3✔
1761
        if err != nil {
3✔
1762
                return nil, fmt.Errorf("failed to query graph: %w", err)
×
1763
        }
×
1764

1765
        return &lnrpc.VerifyMessageResponse{
3✔
1766
                Valid:  active,
3✔
1767
                Pubkey: pubKeyHex,
3✔
1768
        }, nil
3✔
1769
}
1770

1771
// ConnectPeer attempts to establish a connection to a remote peer.
1772
func (r *rpcServer) ConnectPeer(ctx context.Context,
1773
        in *lnrpc.ConnectPeerRequest) (*lnrpc.ConnectPeerResponse, error) {
3✔
1774

3✔
1775
        // The server hasn't yet started, so it won't be able to service any of
3✔
1776
        // our requests, so we'll bail early here.
3✔
1777
        if !r.server.Started() {
3✔
1778
                return nil, ErrServerNotActive
×
1779
        }
×
1780

1781
        if in.Addr == nil {
3✔
1782
                return nil, fmt.Errorf("need: lnc pubkeyhash@hostname")
×
1783
        }
×
1784

1785
        pubkeyHex, err := hex.DecodeString(in.Addr.Pubkey)
3✔
1786
        if err != nil {
3✔
1787
                return nil, err
×
1788
        }
×
1789
        pubKey, err := btcec.ParsePubKey(pubkeyHex)
3✔
1790
        if err != nil {
3✔
1791
                return nil, err
×
1792
        }
×
1793

1794
        // Connections to ourselves are disallowed for obvious reasons.
1795
        if pubKey.IsEqual(r.server.identityECDH.PubKey()) {
3✔
1796
                return nil, fmt.Errorf("cannot make connection to self")
×
1797
        }
×
1798

1799
        addr, err := parseAddr(in.Addr.Host, r.cfg.net)
3✔
1800
        if err != nil {
3✔
1801
                return nil, err
×
1802
        }
×
1803

1804
        peerAddr := &lnwire.NetAddress{
3✔
1805
                IdentityKey: pubKey,
3✔
1806
                Address:     addr,
3✔
1807
                ChainNet:    r.cfg.ActiveNetParams.Net,
3✔
1808
        }
3✔
1809

3✔
1810
        rpcsLog.Debugf("[connectpeer] requested connection to %x@%s",
3✔
1811
                peerAddr.IdentityKey.SerializeCompressed(), peerAddr.Address)
3✔
1812

3✔
1813
        // By default, we will use the global connection timeout value.
3✔
1814
        timeout := r.cfg.ConnectionTimeout
3✔
1815

3✔
1816
        // Check if the connection timeout is set. If set, we will use it in our
3✔
1817
        // request.
3✔
1818
        if in.Timeout != 0 {
6✔
1819
                timeout = time.Duration(in.Timeout) * time.Second
3✔
1820
                rpcsLog.Debugf("[connectpeer] connection timeout is set to %v",
3✔
1821
                        timeout)
3✔
1822
        }
3✔
1823

1824
        if err := r.server.ConnectToPeer(
3✔
1825
                peerAddr, in.Perm, timeout,
3✔
1826
        ); err != nil {
6✔
1827
                rpcsLog.Errorf("[connectpeer]: error connecting to peer: %v",
3✔
1828
                        err)
3✔
1829
                return nil, err
3✔
1830
        }
3✔
1831

1832
        rpcsLog.Debugf("Connected to peer: %v", peerAddr.String())
3✔
1833

3✔
1834
        return &lnrpc.ConnectPeerResponse{
3✔
1835
                Status: fmt.Sprintf("connection to %v initiated",
3✔
1836
                        peerAddr.String()),
3✔
1837
        }, nil
3✔
1838
}
1839

1840
// DisconnectPeer attempts to disconnect one peer from another identified by a
1841
// given pubKey. In the case that we currently have a pending or active channel
1842
// with the target peer, this action will be disallowed.
1843
func (r *rpcServer) DisconnectPeer(ctx context.Context,
1844
        in *lnrpc.DisconnectPeerRequest) (*lnrpc.DisconnectPeerResponse, error) {
3✔
1845

3✔
1846
        rpcsLog.Debugf("[disconnectpeer] from peer(%s)", in.PubKey)
3✔
1847

3✔
1848
        if !r.server.Started() {
3✔
1849
                return nil, ErrServerNotActive
×
1850
        }
×
1851

1852
        // First we'll validate the string passed in within the request to
1853
        // ensure that it's a valid hex-string, and also a valid compressed
1854
        // public key.
1855
        pubKeyBytes, err := hex.DecodeString(in.PubKey)
3✔
1856
        if err != nil {
3✔
1857
                return nil, fmt.Errorf("unable to decode pubkey bytes: %w", err)
×
1858
        }
×
1859
        peerPubKey, err := btcec.ParsePubKey(pubKeyBytes)
3✔
1860
        if err != nil {
3✔
1861
                return nil, fmt.Errorf("unable to parse pubkey: %w", err)
×
1862
        }
×
1863

1864
        // Next, we'll fetch the pending/active channels we have with a
1865
        // particular peer.
1866
        nodeChannels, err := r.server.chanStateDB.FetchOpenChannels(peerPubKey)
3✔
1867
        if err != nil {
3✔
1868
                return nil, fmt.Errorf("unable to fetch channels for peer: %w",
×
1869
                        err)
×
1870
        }
×
1871

1872
        // In order to avoid erroneously disconnecting from a peer that we have
1873
        // an active channel with, if we have any channels active with this
1874
        // peer, then we'll disallow disconnecting from them.
1875
        if len(nodeChannels) != 0 {
6✔
1876
                // If we are not in a dev environment or the configed dev value
3✔
1877
                // `unsafedisconnect` is false, we return an error since there
3✔
1878
                // are active channels.
3✔
1879
                if !r.cfg.Dev.GetUnsafeDisconnect() {
3✔
1880
                        return nil, fmt.Errorf("cannot disconnect from "+
×
1881
                                "peer(%x), still has %d active channels",
×
1882
                                pubKeyBytes, len(nodeChannels))
×
1883
                }
×
1884

1885
                // We are in a dev environment, print a warning log and
1886
                // disconnect.
1887
                rpcsLog.Warnf("UnsafeDisconnect mode, disconnecting from "+
3✔
1888
                        "peer(%x) while there are %d active channels",
3✔
1889
                        pubKeyBytes, len(nodeChannels))
3✔
1890
        }
1891

1892
        // With all initial validation complete, we'll now request that the
1893
        // server disconnects from the peer.
1894
        err = r.server.DisconnectPeer(peerPubKey)
3✔
1895
        if err != nil {
3✔
1896
                return nil, fmt.Errorf("unable to disconnect peer: %w", err)
×
1897
        }
×
1898

1899
        return &lnrpc.DisconnectPeerResponse{
3✔
1900
                Status: "disconnect initiated",
3✔
1901
        }, nil
3✔
1902
}
1903

1904
// newFundingShimAssembler returns a new fully populated
1905
// chanfunding.CannedAssembler using a FundingShim obtained from an RPC caller.
1906
func newFundingShimAssembler(chanPointShim *lnrpc.ChanPointShim, initiator bool,
1907
        keyRing keychain.KeyRing) (chanfunding.Assembler, error) {
3✔
1908

3✔
1909
        // Perform some basic sanity checks to ensure that all the expected
3✔
1910
        // fields are populated.
3✔
1911
        switch {
3✔
1912
        case chanPointShim.RemoteKey == nil:
×
1913
                return nil, fmt.Errorf("remote key not set")
×
1914

1915
        case chanPointShim.LocalKey == nil:
×
1916
                return nil, fmt.Errorf("local key desc not set")
×
1917

1918
        case chanPointShim.LocalKey.RawKeyBytes == nil:
×
1919
                return nil, fmt.Errorf("local raw key bytes not set")
×
1920

1921
        case chanPointShim.LocalKey.KeyLoc == nil:
×
1922
                return nil, fmt.Errorf("local key loc not set")
×
1923

1924
        case chanPointShim.ChanPoint == nil:
×
1925
                return nil, fmt.Errorf("chan point not set")
×
1926

1927
        case len(chanPointShim.PendingChanId) != 32:
×
1928
                return nil, fmt.Errorf("pending chan ID not set")
×
1929
        }
1930

1931
        // First, we'll map the RPC's channel point to one we can actually use.
1932
        index := chanPointShim.ChanPoint.OutputIndex
3✔
1933
        txid, err := lnrpc.GetChanPointFundingTxid(chanPointShim.ChanPoint)
3✔
1934
        if err != nil {
3✔
1935
                return nil, err
×
1936
        }
×
1937
        chanPoint := wire.NewOutPoint(txid, index)
3✔
1938

3✔
1939
        // Next we'll parse out the remote party's funding key, as well as our
3✔
1940
        // full key descriptor.
3✔
1941
        remoteKey, err := btcec.ParsePubKey(chanPointShim.RemoteKey)
3✔
1942
        if err != nil {
3✔
1943
                return nil, err
×
1944
        }
×
1945

1946
        shimKeyDesc := chanPointShim.LocalKey
3✔
1947
        localKey, err := btcec.ParsePubKey(shimKeyDesc.RawKeyBytes)
3✔
1948
        if err != nil {
3✔
1949
                return nil, err
×
1950
        }
×
1951
        localKeyDesc := keychain.KeyDescriptor{
3✔
1952
                PubKey: localKey,
3✔
1953
                KeyLocator: keychain.KeyLocator{
3✔
1954
                        Family: keychain.KeyFamily(
3✔
1955
                                shimKeyDesc.KeyLoc.KeyFamily,
3✔
1956
                        ),
3✔
1957
                        Index: uint32(shimKeyDesc.KeyLoc.KeyIndex),
3✔
1958
                },
3✔
1959
        }
3✔
1960

3✔
1961
        // Verify that if we re-derive this key according to the passed
3✔
1962
        // KeyLocator, that we get the exact same key back. Otherwise, we may
3✔
1963
        // end up in a situation where we aren't able to actually sign for this
3✔
1964
        // newly created channel.
3✔
1965
        derivedKey, err := keyRing.DeriveKey(localKeyDesc.KeyLocator)
3✔
1966
        if err != nil {
3✔
1967
                return nil, err
×
1968
        }
×
1969
        if !derivedKey.PubKey.IsEqual(localKey) {
3✔
1970
                return nil, fmt.Errorf("KeyLocator does not match attached " +
×
1971
                        "raw pubkey")
×
1972
        }
×
1973

1974
        // With all the parts assembled, we can now make the canned assembler
1975
        // to pass into the wallet.
1976
        //
1977
        // TODO(roasbeef): update to support musig2
1978
        return chanfunding.NewCannedAssembler(
3✔
1979
                chanPointShim.ThawHeight, *chanPoint,
3✔
1980
                btcutil.Amount(chanPointShim.Amt), &localKeyDesc,
3✔
1981
                remoteKey, initiator, chanPointShim.Musig2,
3✔
1982
        ), nil
3✔
1983
}
1984

1985
// newPsbtAssembler returns a new fully populated
1986
// chanfunding.PsbtAssembler using a FundingShim obtained from an RPC caller.
1987
func newPsbtAssembler(req *lnrpc.OpenChannelRequest,
1988
        psbtShim *lnrpc.PsbtShim, netParams *chaincfg.Params) (
1989
        chanfunding.Assembler, error) {
3✔
1990

3✔
1991
        var (
3✔
1992
                packet *psbt.Packet
3✔
1993
                err    error
3✔
1994
        )
3✔
1995

3✔
1996
        // Perform some basic sanity checks to ensure that all the expected
3✔
1997
        // fields are populated and none of the incompatible fields are.
3✔
1998
        if len(psbtShim.PendingChanId) != 32 {
3✔
1999
                return nil, fmt.Errorf("pending chan ID not set")
×
2000
        }
×
2001
        if req.SatPerByte != 0 || req.SatPerVbyte != 0 || req.TargetConf != 0 { // nolint:staticcheck
3✔
2002
                return nil, fmt.Errorf("specifying fee estimation parameters " +
×
2003
                        "is not supported for PSBT funding")
×
2004
        }
×
2005

2006
        // The base PSBT is optional. But if it's set, it has to be a valid,
2007
        // binary serialized PSBT.
2008
        if len(psbtShim.BasePsbt) > 0 {
6✔
2009
                packet, err = psbt.NewFromRawBytes(
3✔
2010
                        bytes.NewReader(psbtShim.BasePsbt), false,
3✔
2011
                )
3✔
2012
                if err != nil {
3✔
2013
                        return nil, fmt.Errorf("error parsing base PSBT: %w",
×
2014
                                err)
×
2015
                }
×
2016
        }
2017

2018
        // With all the parts assembled, we can now make the canned assembler
2019
        // to pass into the wallet.
2020
        return chanfunding.NewPsbtAssembler(
3✔
2021
                btcutil.Amount(req.LocalFundingAmount), packet, netParams,
3✔
2022
                !psbtShim.NoPublish,
3✔
2023
        ), nil
3✔
2024
}
2025

2026
// canOpenChannel returns an error if the necessary subsystems for channel
2027
// funding are not ready.
2028
func (r *rpcServer) canOpenChannel() error {
3✔
2029
        // We can't open a channel until the main server has started.
3✔
2030
        if !r.server.Started() {
3✔
2031
                return ErrServerNotActive
×
2032
        }
×
2033

2034
        // Creation of channels before the wallet syncs up is currently
2035
        // disallowed.
2036
        isSynced, _, err := r.server.cc.Wallet.IsSynced()
3✔
2037
        if err != nil {
3✔
2038
                return err
×
2039
        }
×
2040
        if !isSynced {
3✔
2041
                return errors.New("channels cannot be created before the " +
×
2042
                        "wallet is fully synced")
×
2043
        }
×
2044

2045
        return nil
3✔
2046
}
2047

2048
// parseOpenChannelReq parses an OpenChannelRequest message into an InitFundingMsg
2049
// struct. The logic is abstracted so that it can be shared between OpenChannel
2050
// and OpenChannelSync.
2051
func (r *rpcServer) parseOpenChannelReq(in *lnrpc.OpenChannelRequest,
2052
        isSync bool) (*funding.InitFundingMsg, error) {
3✔
2053

3✔
2054
        rpcsLog.Debugf("[openchannel] request to NodeKey(%x) "+
3✔
2055
                "allocation(us=%v, them=%v)", in.NodePubkey,
3✔
2056
                in.LocalFundingAmount, in.PushSat)
3✔
2057

3✔
2058
        localFundingAmt := btcutil.Amount(in.LocalFundingAmount)
3✔
2059
        remoteInitialBalance := btcutil.Amount(in.PushSat)
3✔
2060

3✔
2061
        // If we are not committing the maximum viable balance towards a channel
3✔
2062
        // then the local funding amount must be specified. In case FundMax is
3✔
2063
        // set the funding amount is specified as the interval between minimum
3✔
2064
        // funding amount and by the configured maximum channel size.
3✔
2065
        if !in.FundMax && localFundingAmt == 0 {
3✔
2066
                return nil, fmt.Errorf("local funding amount must be non-zero")
×
2067
        }
×
2068

2069
        // Ensure that the initial balance of the remote party (if pushing
2070
        // satoshis) does not exceed the amount the local party has requested
2071
        // for funding. This is only checked if we are not committing the
2072
        // maximum viable amount towards the channel balance. If we do commit
2073
        // the maximum then the remote balance is checked in a dedicated FundMax
2074
        // check.
2075
        if !in.FundMax && remoteInitialBalance >= localFundingAmt {
3✔
2076
                return nil, fmt.Errorf("amount pushed to remote peer for " +
×
2077
                        "initial state must be below the local funding amount")
×
2078
        }
×
2079

2080
        // We either allow the fundmax or the psbt flow hence we return an error
2081
        // if both are set.
2082
        if in.FundingShim != nil && in.FundMax {
3✔
2083
                return nil, fmt.Errorf("cannot provide a psbt funding shim " +
×
2084
                        "while committing the maximum wallet balance towards " +
×
2085
                        "the channel opening")
×
2086
        }
×
2087

2088
        // If the FundMax flag is set, ensure that the acceptable minimum local
2089
        // amount adheres to the amount to be pushed to the remote, and to
2090
        // current rules, while also respecting the settings for the maximum
2091
        // channel size.
2092
        var minFundAmt, fundUpToMaxAmt btcutil.Amount
3✔
2093
        if in.FundMax {
6✔
2094
                // We assume the configured maximum channel size to be the upper
3✔
2095
                // bound of our "maxed" out funding attempt.
3✔
2096
                fundUpToMaxAmt = btcutil.Amount(r.cfg.MaxChanSize)
3✔
2097

3✔
2098
                // Since the standard non-fundmax flow requires the minimum
3✔
2099
                // funding amount to be at least in the amount of the initial
3✔
2100
                // remote balance(push amount) we need to adjust the minimum
3✔
2101
                // funding amount accordingly. We initially assume the minimum
3✔
2102
                // allowed channel size as minimum funding amount.
3✔
2103
                minFundAmt = funding.MinChanFundingSize
3✔
2104

3✔
2105
                // If minFundAmt is less than the initial remote balance we
3✔
2106
                // simply assign the initial remote balance to minFundAmt in
3✔
2107
                // order to fullfil the criterion. Whether or not this so
3✔
2108
                // determined minimum amount is actually available is
3✔
2109
                // ascertained downstream in the lnwallet's reservation
3✔
2110
                // workflow.
3✔
2111
                if remoteInitialBalance >= minFundAmt {
6✔
2112
                        minFundAmt = remoteInitialBalance
3✔
2113
                }
3✔
2114
        }
2115

2116
        minHtlcIn := lnwire.MilliSatoshi(in.MinHtlcMsat)
3✔
2117
        remoteCsvDelay := uint16(in.RemoteCsvDelay)
3✔
2118
        maxValue := lnwire.MilliSatoshi(in.RemoteMaxValueInFlightMsat)
3✔
2119
        maxHtlcs := uint16(in.RemoteMaxHtlcs)
3✔
2120
        remoteChanReserve := btcutil.Amount(in.RemoteChanReserveSat)
3✔
2121

3✔
2122
        globalFeatureSet := r.server.featureMgr.Get(feature.SetNodeAnn)
3✔
2123

3✔
2124
        // Determine if the user provided channel fees
3✔
2125
        // and if so pass them on to the funding workflow.
3✔
2126
        var channelBaseFee, channelFeeRate *uint64
3✔
2127
        if in.UseBaseFee {
6✔
2128
                channelBaseFee = &in.BaseFee
3✔
2129
        }
3✔
2130
        if in.UseFeeRate {
6✔
2131
                channelFeeRate = &in.FeeRate
3✔
2132
        }
3✔
2133

2134
        // Ensure that the remote channel reserve does not exceed 20% of the
2135
        // channel capacity.
2136
        if !in.FundMax && remoteChanReserve >= localFundingAmt/5 {
3✔
2137
                return nil, fmt.Errorf("remote channel reserve must be less " +
×
2138
                        "than the %%20 of the channel capacity")
×
2139
        }
×
2140

2141
        // Ensure that the user doesn't exceed the current soft-limit for
2142
        // channel size. If the funding amount is above the soft-limit, then
2143
        // we'll reject the request.
2144
        // If the FundMax flag is set the local amount is determined downstream
2145
        // in the wallet hence we do not check it here against the maximum
2146
        // funding amount. Only if the localFundingAmt is specified we can check
2147
        // if it exceeds the maximum funding amount.
2148
        wumboEnabled := globalFeatureSet.HasFeature(
3✔
2149
                lnwire.WumboChannelsOptional,
3✔
2150
        )
3✔
2151
        if !in.FundMax && !wumboEnabled && localFundingAmt > MaxFundingAmount {
3✔
2152
                return nil, fmt.Errorf("funding amount is too large, the max "+
×
2153
                        "channel size is: %v", MaxFundingAmount)
×
2154
        }
×
2155

2156
        // Restrict the size of the channel we'll actually open. At a later
2157
        // level, we'll ensure that the output we create, after accounting for
2158
        // fees, does not leave a dust output. In case of the FundMax flow
2159
        // dedicated checks ensure that the lower boundary of the channel size
2160
        // is at least in the amount of MinChanFundingSize or potentially higher
2161
        // if a remote balance is specified.
2162
        if !in.FundMax && localFundingAmt < funding.MinChanFundingSize {
6✔
2163
                return nil, fmt.Errorf("channel is too small, the minimum "+
3✔
2164
                        "channel size is: %v SAT", int64(funding.MinChanFundingSize))
3✔
2165
        }
3✔
2166

2167
        // Prevent users from submitting a max-htlc value that would exceed the
2168
        // protocol maximum.
2169
        if maxHtlcs > input.MaxHTLCNumber/2 {
3✔
2170
                return nil, fmt.Errorf("remote-max-htlcs (%v) cannot be "+
×
2171
                        "greater than %v", maxHtlcs, input.MaxHTLCNumber/2)
×
2172
        }
×
2173

2174
        // Then, we'll extract the minimum number of confirmations that each
2175
        // output we use to fund the channel's funding transaction should
2176
        // satisfy.
2177
        minConfs, err := lnrpc.ExtractMinConfs(in.MinConfs, in.SpendUnconfirmed)
3✔
2178
        if err != nil {
3✔
2179
                return nil, err
×
2180
        }
×
2181

2182
        // TODO(roasbeef): also return channel ID?
2183

2184
        var nodePubKey *btcec.PublicKey
3✔
2185

3✔
2186
        // Parse the remote pubkey the NodePubkey field of the request. If it's
3✔
2187
        // not present, we'll fallback to the deprecated version that parses the
3✔
2188
        // key from a hex string if this is for REST for backwards compatibility.
3✔
2189
        switch {
3✔
2190
        // Parse the raw bytes of the node key into a pubkey object so we can
2191
        // easily manipulate it.
2192
        case len(in.NodePubkey) > 0:
3✔
2193
                nodePubKey, err = btcec.ParsePubKey(in.NodePubkey)
3✔
2194
                if err != nil {
3✔
2195
                        return nil, err
×
2196
                }
×
2197

2198
        // Decode the provided target node's public key, parsing it into a pub
2199
        // key object. For all sync call, byte slices are expected to be encoded
2200
        // as hex strings.
2201
        case isSync:
×
2202
                keyBytes, err := hex.DecodeString(in.NodePubkeyString) // nolint:staticcheck
×
2203
                if err != nil {
×
2204
                        return nil, err
×
2205
                }
×
2206

2207
                nodePubKey, err = btcec.ParsePubKey(keyBytes)
×
2208
                if err != nil {
×
2209
                        return nil, err
×
2210
                }
×
2211

2212
        default:
×
2213
                return nil, fmt.Errorf("NodePubkey is not set")
×
2214
        }
2215

2216
        // Making a channel to ourselves wouldn't be of any use, so we
2217
        // explicitly disallow them.
2218
        if nodePubKey.IsEqual(r.server.identityECDH.PubKey()) {
3✔
2219
                return nil, fmt.Errorf("cannot open channel to self")
×
2220
        }
×
2221

2222
        // NOTE: We also need to do the fee rate calculation for the psbt
2223
        // funding flow because the `batchfund` depends on it.
2224
        targetConf := maybeUseDefaultConf(
3✔
2225
                in.SatPerByte, in.SatPerVbyte, uint32(in.TargetConf),
3✔
2226
        )
3✔
2227

3✔
2228
        // Calculate an appropriate fee rate for this transaction.
3✔
2229
        feeRate, err := lnrpc.CalculateFeeRate(
3✔
2230
                uint64(in.SatPerByte), in.SatPerVbyte,
3✔
2231
                targetConf, r.server.cc.FeeEstimator,
3✔
2232
        )
3✔
2233
        if err != nil {
3✔
2234
                return nil, err
×
2235
        }
×
2236

2237
        rpcsLog.Debugf("[openchannel]: using fee of %v sat/kw for "+
3✔
2238
                "funding tx", int64(feeRate))
3✔
2239

3✔
2240
        script, err := chancloser.ParseUpfrontShutdownAddress(
3✔
2241
                in.CloseAddress, r.cfg.ActiveNetParams.Params,
3✔
2242
        )
3✔
2243
        if err != nil {
3✔
2244
                return nil, fmt.Errorf("error parsing upfront shutdown: %w",
×
2245
                        err)
×
2246
        }
×
2247

2248
        var channelType *lnwire.ChannelType
3✔
2249
        switch in.CommitmentType {
3✔
2250
        case lnrpc.CommitmentType_UNKNOWN_COMMITMENT_TYPE:
3✔
2251
                if in.ZeroConf {
3✔
2252
                        return nil, fmt.Errorf("use anchors for zero-conf")
×
2253
                }
×
2254

2255
        case lnrpc.CommitmentType_LEGACY:
3✔
2256
                channelType = new(lnwire.ChannelType)
3✔
2257
                *channelType = lnwire.ChannelType(*lnwire.NewRawFeatureVector())
3✔
2258

2259
        case lnrpc.CommitmentType_STATIC_REMOTE_KEY:
3✔
2260
                channelType = new(lnwire.ChannelType)
3✔
2261
                *channelType = lnwire.ChannelType(*lnwire.NewRawFeatureVector(
3✔
2262
                        lnwire.StaticRemoteKeyRequired,
3✔
2263
                ))
3✔
2264

2265
        case lnrpc.CommitmentType_ANCHORS:
3✔
2266
                channelType = new(lnwire.ChannelType)
3✔
2267
                fv := lnwire.NewRawFeatureVector(
3✔
2268
                        lnwire.StaticRemoteKeyRequired,
3✔
2269
                        lnwire.AnchorsZeroFeeHtlcTxRequired,
3✔
2270
                )
3✔
2271

3✔
2272
                if in.ZeroConf {
6✔
2273
                        fv.Set(lnwire.ZeroConfRequired)
3✔
2274
                }
3✔
2275

2276
                if in.ScidAlias {
6✔
2277
                        fv.Set(lnwire.ScidAliasRequired)
3✔
2278
                }
3✔
2279

2280
                *channelType = lnwire.ChannelType(*fv)
3✔
2281

2282
        case lnrpc.CommitmentType_SCRIPT_ENFORCED_LEASE:
3✔
2283
                channelType = new(lnwire.ChannelType)
3✔
2284
                fv := lnwire.NewRawFeatureVector(
3✔
2285
                        lnwire.StaticRemoteKeyRequired,
3✔
2286
                        lnwire.AnchorsZeroFeeHtlcTxRequired,
3✔
2287
                        lnwire.ScriptEnforcedLeaseRequired,
3✔
2288
                )
3✔
2289

3✔
2290
                if in.ZeroConf {
6✔
2291
                        fv.Set(lnwire.ZeroConfRequired)
3✔
2292
                }
3✔
2293

2294
                if in.ScidAlias {
3✔
2295
                        fv.Set(lnwire.ScidAliasRequired)
×
2296
                }
×
2297

2298
                *channelType = lnwire.ChannelType(*fv)
3✔
2299

2300
        case lnrpc.CommitmentType_SIMPLE_TAPROOT:
3✔
2301
                // If the taproot channel type is being set, then the channel
3✔
2302
                // MUST be private (unadvertised) for now.
3✔
2303
                if !in.Private {
3✔
2304
                        return nil, fmt.Errorf("taproot channels must be " +
×
2305
                                "private")
×
2306
                }
×
2307

2308
                channelType = new(lnwire.ChannelType)
3✔
2309
                fv := lnwire.NewRawFeatureVector(
3✔
2310
                        lnwire.SimpleTaprootChannelsRequiredStaging,
3✔
2311
                )
3✔
2312

3✔
2313
                // TODO(roasbeef): no need for the rest as they're now
3✔
2314
                // implicit?
3✔
2315

3✔
2316
                if in.ZeroConf {
6✔
2317
                        fv.Set(lnwire.ZeroConfRequired)
3✔
2318
                }
3✔
2319

2320
                if in.ScidAlias {
3✔
2321
                        fv.Set(lnwire.ScidAliasRequired)
×
2322
                }
×
2323

2324
                *channelType = lnwire.ChannelType(*fv)
3✔
2325

2326
        case lnrpc.CommitmentType_SIMPLE_TAPROOT_OVERLAY:
×
2327
                // If the taproot overlay channel type is being set, then the
×
2328
                // channel MUST be private.
×
2329
                if !in.Private {
×
2330
                        return nil, fmt.Errorf("taproot overlay channels " +
×
2331
                                "must be private")
×
2332
                }
×
2333

2334
                channelType = new(lnwire.ChannelType)
×
2335
                fv := lnwire.NewRawFeatureVector(
×
2336
                        lnwire.SimpleTaprootOverlayChansRequired,
×
2337
                )
×
2338

×
2339
                if in.ZeroConf {
×
2340
                        fv.Set(lnwire.ZeroConfRequired)
×
2341
                }
×
2342

2343
                if in.ScidAlias {
×
2344
                        fv.Set(lnwire.ScidAliasRequired)
×
2345
                }
×
2346

2347
                *channelType = lnwire.ChannelType(*fv)
×
2348

2349
        default:
×
2350
                return nil, fmt.Errorf("unhandled request channel type %v",
×
2351
                        in.CommitmentType)
×
2352
        }
2353

2354
        // We limit the channel memo to be 500 characters long. This enforces
2355
        // a reasonable upper bound on storage consumption. This also mimics
2356
        // the length limit for the label of a TX.
2357
        const maxMemoLength = 500
3✔
2358
        if len(in.Memo) > maxMemoLength {
6✔
2359
                return nil, fmt.Errorf("provided memo (%s) is of length %d, "+
3✔
2360
                        "exceeds %d", in.Memo, len(in.Memo), maxMemoLength)
3✔
2361
        }
3✔
2362

2363
        // Check, if manually selected outpoints are present to fund a channel.
2364
        var outpoints []wire.OutPoint
3✔
2365
        if len(in.Outpoints) > 0 {
6✔
2366
                outpoints, err = toWireOutpoints(in.Outpoints)
3✔
2367
                if err != nil {
3✔
2368
                        return nil, fmt.Errorf("can't create outpoints %w", err)
×
2369
                }
×
2370
        }
2371

2372
        // Instruct the server to trigger the necessary events to attempt to
2373
        // open a new channel. A stream is returned in place, this stream will
2374
        // be used to consume updates of the state of the pending channel.
2375
        return &funding.InitFundingMsg{
3✔
2376
                TargetPubkey:    nodePubKey,
3✔
2377
                ChainHash:       *r.cfg.ActiveNetParams.GenesisHash,
3✔
2378
                LocalFundingAmt: localFundingAmt,
3✔
2379
                BaseFee:         channelBaseFee,
3✔
2380
                FeeRate:         channelFeeRate,
3✔
2381
                PushAmt: lnwire.NewMSatFromSatoshis(
3✔
2382
                        remoteInitialBalance,
3✔
2383
                ),
3✔
2384
                MinHtlcIn:         minHtlcIn,
3✔
2385
                FundingFeePerKw:   feeRate,
3✔
2386
                Private:           in.Private,
3✔
2387
                RemoteCsvDelay:    remoteCsvDelay,
3✔
2388
                RemoteChanReserve: remoteChanReserve,
3✔
2389
                MinConfs:          minConfs,
3✔
2390
                ShutdownScript:    script,
3✔
2391
                MaxValueInFlight:  maxValue,
3✔
2392
                MaxHtlcs:          maxHtlcs,
3✔
2393
                MaxLocalCsv:       uint16(in.MaxLocalCsv),
3✔
2394
                ChannelType:       channelType,
3✔
2395
                FundUpToMaxAmt:    fundUpToMaxAmt,
3✔
2396
                MinFundAmt:        minFundAmt,
3✔
2397
                Memo:              []byte(in.Memo),
3✔
2398
                Outpoints:         outpoints,
3✔
2399
        }, nil
3✔
2400
}
2401

2402
// toWireOutpoints converts a list of outpoints from the rpc format to the wire
2403
// format.
2404
func toWireOutpoints(outpoints []*lnrpc.OutPoint) ([]wire.OutPoint, error) {
3✔
2405
        var wireOutpoints []wire.OutPoint
3✔
2406
        for _, outpoint := range outpoints {
6✔
2407
                hash, err := chainhash.NewHashFromStr(outpoint.TxidStr)
3✔
2408
                if err != nil {
3✔
2409
                        return nil, fmt.Errorf("cannot create chainhash")
×
2410
                }
×
2411

2412
                wireOutpoint := wire.NewOutPoint(
3✔
2413
                        hash, outpoint.OutputIndex,
3✔
2414
                )
3✔
2415
                wireOutpoints = append(wireOutpoints, *wireOutpoint)
3✔
2416
        }
2417

2418
        return wireOutpoints, nil
3✔
2419
}
2420

2421
// OpenChannel attempts to open a singly funded channel specified in the
2422
// request to a remote peer.
2423
func (r *rpcServer) OpenChannel(in *lnrpc.OpenChannelRequest,
2424
        updateStream lnrpc.Lightning_OpenChannelServer) error {
3✔
2425

3✔
2426
        if err := r.canOpenChannel(); err != nil {
3✔
2427
                return err
×
2428
        }
×
2429

2430
        req, err := r.parseOpenChannelReq(in, false)
3✔
2431
        if err != nil {
6✔
2432
                return err
3✔
2433
        }
3✔
2434

2435
        // If the user has provided a shim, then we'll now augment the based
2436
        // open channel request with this additional logic.
2437
        if in.FundingShim != nil {
6✔
2438
                switch {
3✔
2439
                // If we have a chan point shim, then this means the funding
2440
                // transaction was crafted externally. In this case we only
2441
                // need to hand a channel point down into the wallet.
2442
                case in.FundingShim.GetChanPointShim() != nil:
3✔
2443
                        chanPointShim := in.FundingShim.GetChanPointShim()
3✔
2444

3✔
2445
                        // Map the channel point shim into a new
3✔
2446
                        // chanfunding.CannedAssembler that the wallet will use
3✔
2447
                        // to obtain the channel point details.
3✔
2448
                        copy(req.PendingChanID[:], chanPointShim.PendingChanId)
3✔
2449
                        req.ChanFunder, err = newFundingShimAssembler(
3✔
2450
                                chanPointShim, true, r.server.cc.KeyRing,
3✔
2451
                        )
3✔
2452
                        if err != nil {
3✔
2453
                                return err
×
2454
                        }
×
2455

2456
                // If we have a PSBT shim, then this means the funding
2457
                // transaction will be crafted outside of the wallet, once the
2458
                // funding multisig output script is known. We'll create an
2459
                // intent that will supervise the multi-step process.
2460
                case in.FundingShim.GetPsbtShim() != nil:
3✔
2461
                        psbtShim := in.FundingShim.GetPsbtShim()
3✔
2462

3✔
2463
                        // Instruct the wallet to use the new
3✔
2464
                        // chanfunding.PsbtAssembler to construct the funding
3✔
2465
                        // transaction.
3✔
2466
                        copy(req.PendingChanID[:], psbtShim.PendingChanId)
3✔
2467

3✔
2468
                        // NOTE: For the PSBT case we do also allow unconfirmed
3✔
2469
                        // utxos to fund the psbt transaction because we make
3✔
2470
                        // sure we only use stable utxos.
3✔
2471
                        req.ChanFunder, err = newPsbtAssembler(
3✔
2472
                                in, psbtShim,
3✔
2473
                                &r.server.cc.Wallet.Cfg.NetParams,
3✔
2474
                        )
3✔
2475
                        if err != nil {
3✔
2476
                                return err
×
2477
                        }
×
2478
                }
2479
        }
2480

2481
        updateChan, errChan := r.server.OpenChannel(req)
3✔
2482

3✔
2483
        var outpoint wire.OutPoint
3✔
2484
out:
3✔
2485
        for {
6✔
2486
                select {
3✔
2487
                case err := <-errChan:
3✔
2488
                        rpcsLog.Errorf("unable to open channel to NodeKey(%x): %v",
3✔
2489
                                req.TargetPubkey.SerializeCompressed(), err)
3✔
2490
                        return err
3✔
2491
                case fundingUpdate := <-updateChan:
3✔
2492
                        rpcsLog.Tracef("[openchannel] sending update: %v",
3✔
2493
                                fundingUpdate)
3✔
2494
                        if err := updateStream.Send(fundingUpdate); err != nil {
3✔
2495
                                return err
×
2496
                        }
×
2497

2498
                        // If a final channel open update is being sent, then
2499
                        // we can break out of our recv loop as we no longer
2500
                        // need to process any further updates.
2501
                        update, ok := fundingUpdate.Update.(*lnrpc.OpenStatusUpdate_ChanOpen)
3✔
2502
                        if ok {
6✔
2503
                                chanPoint := update.ChanOpen.ChannelPoint
3✔
2504
                                txid, err := lnrpc.GetChanPointFundingTxid(chanPoint)
3✔
2505
                                if err != nil {
3✔
2506
                                        return err
×
2507
                                }
×
2508
                                outpoint = wire.OutPoint{
3✔
2509
                                        Hash:  *txid,
3✔
2510
                                        Index: chanPoint.OutputIndex,
3✔
2511
                                }
3✔
2512

3✔
2513
                                break out
3✔
2514
                        }
2515
                case <-r.quit:
3✔
2516
                        return nil
3✔
2517
                }
2518
        }
2519

2520
        rpcsLog.Tracef("[openchannel] success NodeKey(%x), ChannelPoint(%v)",
3✔
2521
                req.TargetPubkey.SerializeCompressed(), outpoint)
3✔
2522
        return nil
3✔
2523
}
2524

2525
// OpenChannelSync is a synchronous version of the OpenChannel RPC call. This
2526
// call is meant to be consumed by clients to the REST proxy. As with all other
2527
// sync calls, all byte slices are instead to be populated as hex encoded
2528
// strings.
2529
func (r *rpcServer) OpenChannelSync(ctx context.Context,
2530
        in *lnrpc.OpenChannelRequest) (*lnrpc.ChannelPoint, error) {
×
2531

×
2532
        if err := r.canOpenChannel(); err != nil {
×
2533
                return nil, err
×
2534
        }
×
2535

2536
        req, err := r.parseOpenChannelReq(in, true)
×
2537
        if err != nil {
×
2538
                return nil, err
×
2539
        }
×
2540

2541
        updateChan, errChan := r.server.OpenChannel(req)
×
2542
        select {
×
2543
        // If an error occurs them immediately return the error to the client.
2544
        case err := <-errChan:
×
2545
                rpcsLog.Errorf("unable to open channel to NodeKey(%x): %v",
×
2546
                        req.TargetPubkey.SerializeCompressed(), err)
×
2547
                return nil, err
×
2548

2549
        // Otherwise, wait for the first channel update. The first update sent
2550
        // is when the funding transaction is broadcast to the network.
2551
        case fundingUpdate := <-updateChan:
×
2552
                rpcsLog.Tracef("[openchannel] sending update: %v",
×
2553
                        fundingUpdate)
×
2554

×
2555
                // Parse out the txid of the pending funding transaction. The
×
2556
                // sync client can use this to poll against the list of
×
2557
                // PendingChannels.
×
2558
                openUpdate := fundingUpdate.Update.(*lnrpc.OpenStatusUpdate_ChanPending)
×
2559
                chanUpdate := openUpdate.ChanPending
×
2560

×
2561
                return &lnrpc.ChannelPoint{
×
2562
                        FundingTxid: &lnrpc.ChannelPoint_FundingTxidBytes{
×
2563
                                FundingTxidBytes: chanUpdate.Txid,
×
2564
                        },
×
2565
                        OutputIndex: chanUpdate.OutputIndex,
×
2566
                }, nil
×
2567
        case <-r.quit:
×
2568
                return nil, nil
×
2569
        }
2570
}
2571

2572
// BatchOpenChannel attempts to open multiple single-funded channels in a
2573
// single transaction in an atomic way. This means either all channel open
2574
// requests succeed at once or all attempts are aborted if any of them fail.
2575
// This is the safer variant of using PSBTs to manually fund a batch of
2576
// channels through the OpenChannel RPC.
2577
func (r *rpcServer) BatchOpenChannel(ctx context.Context,
2578
        in *lnrpc.BatchOpenChannelRequest) (*lnrpc.BatchOpenChannelResponse,
2579
        error) {
3✔
2580

3✔
2581
        if err := r.canOpenChannel(); err != nil {
3✔
2582
                return nil, err
×
2583
        }
×
2584

2585
        // We need the wallet kit server to do the heavy lifting on the PSBT
2586
        // part. If we didn't rely on re-using the wallet kit server's logic we
2587
        // would need to re-implement everything here. Since we deliver lnd with
2588
        // the wallet kit server enabled by default we can assume it's okay to
2589
        // make this functionality dependent on that server being active.
2590
        var walletKitServer walletrpc.WalletKitServer
3✔
2591
        for _, subServer := range r.subServers {
6✔
2592
                if subServer.Name() == walletrpc.SubServerName {
6✔
2593
                        walletKitServer = subServer.(walletrpc.WalletKitServer)
3✔
2594
                }
3✔
2595
        }
2596
        if walletKitServer == nil {
3✔
2597
                return nil, fmt.Errorf("batch channel open is only possible " +
×
2598
                        "if walletrpc subserver is active")
×
2599
        }
×
2600

2601
        rpcsLog.Debugf("[batchopenchannel] request to open batch of %d "+
3✔
2602
                "channels", len(in.Channels))
3✔
2603

3✔
2604
        // Make sure there is at least one channel to open. We could say we want
3✔
2605
        // at least two channels for a batch. But maybe it's nice if developers
3✔
2606
        // can use the same API for a single channel as well as a batch of
3✔
2607
        // channels.
3✔
2608
        if len(in.Channels) == 0 {
3✔
2609
                return nil, fmt.Errorf("specify at least one channel")
×
2610
        }
×
2611

2612
        // In case we remove a pending channel from the database, we need to set
2613
        // a close height, so we'll just use the current best known height.
2614
        _, bestHeight, err := r.server.cc.ChainIO.GetBestBlock()
3✔
2615
        if err != nil {
3✔
2616
                return nil, fmt.Errorf("error fetching best block: %w", err)
×
2617
        }
×
2618

2619
        // So far everything looks good and we can now start the heavy lifting
2620
        // that's done in the funding package.
2621
        requestParser := func(req *lnrpc.OpenChannelRequest) (
3✔
2622
                *funding.InitFundingMsg, error) {
6✔
2623

3✔
2624
                return r.parseOpenChannelReq(req, false)
3✔
2625
        }
3✔
2626
        channelAbandoner := func(point *wire.OutPoint) error {
3✔
2627
                return r.abandonChan(point, uint32(bestHeight))
×
2628
        }
×
2629
        batcher := funding.NewBatcher(&funding.BatchConfig{
3✔
2630
                RequestParser:    requestParser,
3✔
2631
                ChannelAbandoner: channelAbandoner,
3✔
2632
                ChannelOpener:    r.server.OpenChannel,
3✔
2633
                WalletKitServer:  walletKitServer,
3✔
2634
                Wallet:           r.server.cc.Wallet,
3✔
2635
                NetParams:        &r.server.cc.Wallet.Cfg.NetParams,
3✔
2636
                Quit:             r.quit,
3✔
2637
        })
3✔
2638
        rpcPoints, err := batcher.BatchFund(ctx, in)
3✔
2639
        if err != nil {
6✔
2640
                return nil, fmt.Errorf("batch funding failed: %w", err)
3✔
2641
        }
3✔
2642

2643
        // Now all that's left to do is send back the response with the channel
2644
        // points we created.
2645
        return &lnrpc.BatchOpenChannelResponse{
3✔
2646
                PendingChannels: rpcPoints,
3✔
2647
        }, nil
3✔
2648
}
2649

2650
// CloseChannel attempts to close an active channel identified by its channel
2651
// point. The actions of this method can additionally be augmented to attempt
2652
// a force close after a timeout period in the case of an inactive peer.
2653
func (r *rpcServer) CloseChannel(in *lnrpc.CloseChannelRequest,
2654
        updateStream lnrpc.Lightning_CloseChannelServer) error {
3✔
2655

3✔
2656
        if !r.server.Started() {
3✔
2657
                return ErrServerNotActive
×
2658
        }
×
2659

2660
        // If the user didn't specify a channel point, then we'll reject this
2661
        // request all together.
2662
        if in.GetChannelPoint() == nil {
3✔
2663
                return fmt.Errorf("must specify channel point in close channel")
×
2664
        }
×
2665

2666
        // If force closing a channel, the fee set in the commitment transaction
2667
        // is used.
2668
        if in.Force && (in.SatPerByte != 0 || in.SatPerVbyte != 0 || // nolint:staticcheck
3✔
2669
                in.TargetConf != 0) {
3✔
2670

×
2671
                return fmt.Errorf("force closing a channel uses a pre-defined fee")
×
2672
        }
×
2673

2674
        force := in.Force
3✔
2675
        index := in.ChannelPoint.OutputIndex
3✔
2676
        txid, err := lnrpc.GetChanPointFundingTxid(in.GetChannelPoint())
3✔
2677
        if err != nil {
3✔
2678
                rpcsLog.Errorf("[closechannel] unable to get funding txid: %v", err)
×
2679
                return err
×
2680
        }
×
2681
        chanPoint := wire.NewOutPoint(txid, index)
3✔
2682

3✔
2683
        rpcsLog.Tracef("[closechannel] request for ChannelPoint(%v), force=%v",
3✔
2684
                chanPoint, force)
3✔
2685

3✔
2686
        var (
3✔
2687
                updateChan chan interface{}
3✔
2688
                errChan    chan error
3✔
2689
        )
3✔
2690

3✔
2691
        // TODO(roasbeef): if force and peer online then don't force?
3✔
2692

3✔
2693
        // First, we'll fetch the channel as is, as we'll need to examine it
3✔
2694
        // regardless of if this is a force close or not.
3✔
2695
        channel, err := r.server.chanStateDB.FetchChannel(*chanPoint)
3✔
2696
        if err != nil {
3✔
2697
                return err
×
2698
        }
×
2699

2700
        // We can't coop or force close restored channels or channels that have
2701
        // experienced local data loss. Normally we would detect this in the
2702
        // channel arbitrator if the channel has the status
2703
        // ChanStatusLocalDataLoss after connecting to its peer. But if no
2704
        // connection can be established, the channel arbitrator doesn't know it
2705
        // can't be force closed yet.
2706
        if channel.HasChanStatus(channeldb.ChanStatusRestored) ||
3✔
2707
                channel.HasChanStatus(channeldb.ChanStatusLocalDataLoss) {
6✔
2708

3✔
2709
                return fmt.Errorf("cannot close channel with state: %v",
3✔
2710
                        channel.ChanStatus())
3✔
2711
        }
3✔
2712

2713
        // Retrieve the best height of the chain, which we'll use to complete
2714
        // either closing flow.
2715
        _, bestHeight, err := r.server.cc.ChainIO.GetBestBlock()
3✔
2716
        if err != nil {
3✔
2717
                return err
×
2718
        }
×
2719

2720
        // If a force closure was requested, then we'll handle all the details
2721
        // around the creation and broadcast of the unilateral closure
2722
        // transaction here rather than going to the switch as we don't require
2723
        // interaction from the peer.
2724
        if force {
6✔
2725
                // As we're force closing this channel, as a precaution, we'll
3✔
2726
                // ensure that the switch doesn't continue to see this channel
3✔
2727
                // as eligible for forwarding HTLC's. If the peer is online,
3✔
2728
                // then we'll also purge all of its indexes.
3✔
2729
                remotePub := channel.IdentityPub
3✔
2730
                if peer, err := r.server.FindPeer(remotePub); err == nil {
6✔
2731
                        // TODO(roasbeef): actually get the active channel
3✔
2732
                        // instead too?
3✔
2733
                        //  * so only need to grab from database
3✔
2734
                        peer.WipeChannel(&channel.FundingOutpoint)
3✔
2735
                } else {
6✔
2736
                        chanID := lnwire.NewChanIDFromOutPoint(
3✔
2737
                                channel.FundingOutpoint,
3✔
2738
                        )
3✔
2739
                        r.server.htlcSwitch.RemoveLink(chanID)
3✔
2740
                }
3✔
2741

2742
                // With the necessary indexes cleaned up, we'll now force close
2743
                // the channel.
2744
                chainArbitrator := r.server.chainArb
3✔
2745
                closingTx, err := chainArbitrator.ForceCloseContract(
3✔
2746
                        *chanPoint,
3✔
2747
                )
3✔
2748
                if err != nil {
3✔
2749
                        rpcsLog.Errorf("unable to force close transaction: %v", err)
×
2750
                        return err
×
2751
                }
×
2752

2753
                // Safety check which should never happen.
2754
                //
2755
                // TODO(ziggie): remove pointer as return value from
2756
                // ForceCloseContract.
2757
                if closingTx == nil {
3✔
2758
                        return fmt.Errorf("force close transaction is nil")
×
2759
                }
×
2760

2761
                closingTxid := closingTx.TxHash()
3✔
2762

3✔
2763
                // With the transaction broadcast, we send our first update to
3✔
2764
                // the client.
3✔
2765
                updateChan = make(chan interface{}, 2)
3✔
2766
                updateChan <- &peer.PendingUpdate{
3✔
2767
                        Txid: closingTxid[:],
3✔
2768
                }
3✔
2769

3✔
2770
                errChan = make(chan error, 1)
3✔
2771
                notifier := r.server.cc.ChainNotifier
3✔
2772
                go peer.WaitForChanToClose(
3✔
2773
                        uint32(bestHeight), notifier, errChan, chanPoint,
3✔
2774
                        &closingTxid, closingTx.TxOut[0].PkScript, func() {
6✔
2775
                                // Respond to the local subsystem which
3✔
2776
                                // requested the channel closure.
3✔
2777
                                updateChan <- &peer.ChannelCloseUpdate{
3✔
2778
                                        ClosingTxid: closingTxid[:],
3✔
2779
                                        Success:     true,
3✔
2780
                                        // Force closure transactions don't have
3✔
2781
                                        // additional local/remote outputs.
3✔
2782
                                }
3✔
2783
                        },
3✔
2784
                )
2785
        } else {
3✔
2786
                // If this is a frozen channel, then we only allow the co-op
3✔
2787
                // close to proceed if we were the responder to this channel if
3✔
2788
                // the absolute thaw height has not been met.
3✔
2789
                if channel.IsInitiator {
6✔
2790
                        absoluteThawHeight, err := channel.AbsoluteThawHeight()
3✔
2791
                        if err != nil {
3✔
2792
                                return err
×
2793
                        }
×
2794
                        if uint32(bestHeight) < absoluteThawHeight {
6✔
2795
                                return fmt.Errorf("cannot co-op close frozen "+
3✔
2796
                                        "channel as initiator until height=%v, "+
3✔
2797
                                        "(current_height=%v)",
3✔
2798
                                        absoluteThawHeight, bestHeight)
3✔
2799
                        }
3✔
2800
                }
2801

2802
                // If the link is not known by the switch, we cannot gracefully close
2803
                // the channel.
2804
                channelID := lnwire.NewChanIDFromOutPoint(*chanPoint)
3✔
2805
                if _, err := r.server.htlcSwitch.GetLink(channelID); err != nil {
3✔
2806
                        rpcsLog.Debugf("Trying to non-force close offline channel with "+
×
2807
                                "chan_point=%v", chanPoint)
×
2808
                        return fmt.Errorf("unable to gracefully close channel while peer "+
×
2809
                                "is offline (try force closing it instead): %v", err)
×
2810
                }
×
2811

2812
                // Keep the old behavior prior to 0.18.0 - when the user
2813
                // doesn't set fee rate or conf target, the default conf target
2814
                // of 6 is used.
2815
                targetConf := maybeUseDefaultConf(
3✔
2816
                        in.SatPerByte, in.SatPerVbyte, uint32(in.TargetConf),
3✔
2817
                )
3✔
2818

3✔
2819
                // Based on the passed fee related parameters, we'll determine
3✔
2820
                // an appropriate fee rate for the cooperative closure
3✔
2821
                // transaction.
3✔
2822
                feeRate, err := lnrpc.CalculateFeeRate(
3✔
2823
                        uint64(in.SatPerByte), in.SatPerVbyte, // nolint:staticcheck
3✔
2824
                        targetConf, r.server.cc.FeeEstimator,
3✔
2825
                )
3✔
2826
                if err != nil {
3✔
2827
                        return err
×
2828
                }
×
2829

2830
                rpcsLog.Debugf("Target sat/kw for closing transaction: %v",
3✔
2831
                        int64(feeRate))
3✔
2832

3✔
2833
                // If the user hasn't specified NoWait, then before we attempt
3✔
2834
                // to close the channel we ensure there are no active HTLCs on
3✔
2835
                // the link.
3✔
2836
                if !in.NoWait && len(channel.ActiveHtlcs()) != 0 {
3✔
2837
                        return fmt.Errorf("cannot co-op close channel " +
×
2838
                                "with active htlcs")
×
2839
                }
×
2840

2841
                // Otherwise, the caller has requested a regular interactive
2842
                // cooperative channel closure. So we'll forward the request to
2843
                // the htlc switch which will handle the negotiation and
2844
                // broadcast details.
2845

2846
                var deliveryScript lnwire.DeliveryAddress
3✔
2847

3✔
2848
                // If a delivery address to close out to was specified, decode it.
3✔
2849
                if len(in.DeliveryAddress) > 0 {
6✔
2850
                        // Decode the address provided.
3✔
2851
                        addr, err := btcutil.DecodeAddress(
3✔
2852
                                in.DeliveryAddress, r.cfg.ActiveNetParams.Params,
3✔
2853
                        )
3✔
2854
                        if err != nil {
3✔
2855
                                return fmt.Errorf("invalid delivery address: "+
×
2856
                                        "%v", err)
×
2857
                        }
×
2858

2859
                        if !addr.IsForNet(r.cfg.ActiveNetParams.Params) {
3✔
2860
                                return fmt.Errorf("delivery address is not "+
×
2861
                                        "for %s",
×
2862
                                        r.cfg.ActiveNetParams.Params.Name)
×
2863
                        }
×
2864

2865
                        // Create a script to pay out to the address provided.
2866
                        deliveryScript, err = txscript.PayToAddrScript(addr)
3✔
2867
                        if err != nil {
3✔
2868
                                return err
×
2869
                        }
×
2870
                }
2871

2872
                maxFee := chainfee.SatPerKVByte(
3✔
2873
                        in.MaxFeePerVbyte * 1000,
3✔
2874
                ).FeePerKWeight()
3✔
2875
                updateChan, errChan = r.server.htlcSwitch.CloseLink(
3✔
2876
                        chanPoint, contractcourt.CloseRegular, feeRate,
3✔
2877
                        maxFee, deliveryScript,
3✔
2878
                )
3✔
2879
        }
2880

2881
        // If the user doesn't want to wait for the txid to come back then we
2882
        // will send an empty update to kick off the stream.
2883
        if in.NoWait {
6✔
2884
                rpcsLog.Trace("[closechannel] sending instant update")
3✔
2885
                if err := updateStream.Send(
3✔
2886
                        &lnrpc.CloseStatusUpdate{
3✔
2887
                                Update: &lnrpc.CloseStatusUpdate_CloseInstant{},
3✔
2888
                        },
3✔
2889
                ); err != nil {
3✔
2890
                        return err
×
2891
                }
×
2892
        }
2893
out:
3✔
2894
        for {
6✔
2895
                select {
3✔
2896
                case err := <-errChan:
×
2897
                        rpcsLog.Errorf("[closechannel] unable to close "+
×
2898
                                "ChannelPoint(%v): %v", chanPoint, err)
×
2899
                        return err
×
2900
                case closingUpdate := <-updateChan:
3✔
2901
                        rpcClosingUpdate, err := createRPCCloseUpdate(
3✔
2902
                                closingUpdate,
3✔
2903
                        )
3✔
2904
                        if err != nil {
3✔
2905
                                return err
×
2906
                        }
×
2907

2908
                        err = fn.MapOptionZ(
3✔
2909
                                r.server.implCfg.AuxDataParser,
3✔
2910
                                func(parser AuxDataParser) error {
3✔
2911
                                        return parser.InlineParseCustomData(
×
2912
                                                rpcClosingUpdate,
×
2913
                                        )
×
2914
                                },
×
2915
                        )
2916
                        if err != nil {
3✔
2917
                                return fmt.Errorf("error parsing custom data: "+
×
2918
                                        "%w", err)
×
2919
                        }
×
2920

2921
                        rpcsLog.Tracef("[closechannel] sending update: %v",
3✔
2922
                                rpcClosingUpdate)
3✔
2923

3✔
2924
                        if err := updateStream.Send(rpcClosingUpdate); err != nil {
3✔
2925
                                return err
×
2926
                        }
×
2927

2928
                        // If a final channel closing updates is being sent,
2929
                        // then we can break out of our dispatch loop as we no
2930
                        // longer need to process any further updates.
2931
                        switch closeUpdate := closingUpdate.(type) {
3✔
2932
                        case *peer.ChannelCloseUpdate:
3✔
2933
                                h, _ := chainhash.NewHash(closeUpdate.ClosingTxid)
3✔
2934
                                rpcsLog.Infof("[closechannel] close completed: "+
3✔
2935
                                        "txid(%v)", h)
3✔
2936
                                break out
3✔
2937
                        }
2938
                case <-r.quit:
3✔
2939
                        return nil
3✔
2940
                }
2941
        }
2942

2943
        return nil
3✔
2944
}
2945

2946
func createRPCCloseUpdate(
2947
        update interface{}) (*lnrpc.CloseStatusUpdate, error) {
3✔
2948

3✔
2949
        switch u := update.(type) {
3✔
2950
        case *peer.ChannelCloseUpdate:
3✔
2951
                ccu := &lnrpc.ChannelCloseUpdate{
3✔
2952
                        ClosingTxid: u.ClosingTxid,
3✔
2953
                        Success:     u.Success,
3✔
2954
                }
3✔
2955

3✔
2956
                err := fn.MapOptionZ(
3✔
2957
                        u.LocalCloseOutput,
3✔
2958
                        func(closeOut chancloser.CloseOutput) error {
6✔
2959
                                cr, err := closeOut.ShutdownRecords.Serialize()
3✔
2960
                                if err != nil {
3✔
2961
                                        return fmt.Errorf("error serializing "+
×
2962
                                                "local close out custom "+
×
2963
                                                "records: %w", err)
×
2964
                                }
×
2965

2966
                                rpcCloseOut := &lnrpc.CloseOutput{
3✔
2967
                                        AmountSat:         int64(closeOut.Amt),
3✔
2968
                                        PkScript:          closeOut.PkScript,
3✔
2969
                                        IsLocal:           true,
3✔
2970
                                        CustomChannelData: cr,
3✔
2971
                                }
3✔
2972
                                ccu.LocalCloseOutput = rpcCloseOut
3✔
2973

3✔
2974
                                return nil
3✔
2975
                        },
2976
                )
2977
                if err != nil {
3✔
2978
                        return nil, err
×
2979
                }
×
2980

2981
                err = fn.MapOptionZ(
3✔
2982
                        u.RemoteCloseOutput,
3✔
2983
                        func(closeOut chancloser.CloseOutput) error {
6✔
2984
                                cr, err := closeOut.ShutdownRecords.Serialize()
3✔
2985
                                if err != nil {
3✔
2986
                                        return fmt.Errorf("error serializing "+
×
2987
                                                "remote close out custom "+
×
2988
                                                "records: %w", err)
×
2989
                                }
×
2990

2991
                                rpcCloseOut := &lnrpc.CloseOutput{
3✔
2992
                                        AmountSat:         int64(closeOut.Amt),
3✔
2993
                                        PkScript:          closeOut.PkScript,
3✔
2994
                                        CustomChannelData: cr,
3✔
2995
                                }
3✔
2996
                                ccu.RemoteCloseOutput = rpcCloseOut
3✔
2997

3✔
2998
                                return nil
3✔
2999
                        },
3000
                )
3001
                if err != nil {
3✔
3002
                        return nil, err
×
3003
                }
×
3004

3005
                u.AuxOutputs.WhenSome(func(outs chancloser.AuxCloseOutputs) {
3✔
3006
                        for _, out := range outs.ExtraCloseOutputs {
×
3007
                                ccu.AdditionalOutputs = append(
×
3008
                                        ccu.AdditionalOutputs,
×
3009
                                        &lnrpc.CloseOutput{
×
3010
                                                AmountSat: out.Value,
×
3011
                                                PkScript:  out.PkScript,
×
3012
                                                IsLocal:   out.IsLocal,
×
3013
                                        },
×
3014
                                )
×
3015
                        }
×
3016
                })
3017

3018
                return &lnrpc.CloseStatusUpdate{
3✔
3019
                        Update: &lnrpc.CloseStatusUpdate_ChanClose{
3✔
3020
                                ChanClose: ccu,
3✔
3021
                        },
3✔
3022
                }, nil
3✔
3023

3024
        case *peer.PendingUpdate:
3✔
3025
                return &lnrpc.CloseStatusUpdate{
3✔
3026
                        Update: &lnrpc.CloseStatusUpdate_ClosePending{
3✔
3027
                                ClosePending: &lnrpc.PendingUpdate{
3✔
3028
                                        Txid:        u.Txid,
3✔
3029
                                        OutputIndex: u.OutputIndex,
3✔
3030
                                },
3✔
3031
                        },
3✔
3032
                }, nil
3✔
3033
        }
3034

3035
        return nil, errors.New("unknown close status update")
×
3036
}
3037

3038
// abandonChanFromGraph attempts to remove a channel from the channel graph. If
3039
// we can't find the chanID in the graph, then we assume it has already been
3040
// removed, and will return a nop.
3041
func abandonChanFromGraph(chanGraph *graphdb.ChannelGraph,
3042
        chanPoint *wire.OutPoint) error {
3✔
3043

3✔
3044
        // First, we'll obtain the channel ID. If we can't locate this, then
3✔
3045
        // it's the case that the channel may have already been removed from
3✔
3046
        // the graph, so we'll return a nil error.
3✔
3047
        chanID, err := chanGraph.ChannelID(chanPoint)
3✔
3048
        switch {
3✔
3049
        case errors.Is(err, graphdb.ErrEdgeNotFound):
3✔
3050
                return nil
3✔
3051
        case err != nil:
×
3052
                return err
×
3053
        }
3054

3055
        // If the channel ID is still in the graph, then that means the channel
3056
        // is still open, so we'll now move to purge it from the graph.
3057
        return chanGraph.DeleteChannelEdges(false, true, chanID)
3✔
3058
}
3059

3060
// abandonChan removes a channel from the database, graph and contract court.
3061
func (r *rpcServer) abandonChan(chanPoint *wire.OutPoint,
3062
        bestHeight uint32) error {
3✔
3063

3✔
3064
        // Before we remove the channel we cancel the rebroadcasting of the
3✔
3065
        // transaction. If this transaction does not exist in the rebroadcast
3✔
3066
        // queue anymore it is a noop.
3✔
3067
        txid, err := chainhash.NewHash(chanPoint.Hash[:])
3✔
3068
        if err != nil {
3✔
3069
                return err
×
3070
        }
×
3071
        r.server.cc.Wallet.CancelRebroadcast(*txid)
3✔
3072

3✔
3073
        // Abandoning a channel is a three-step process: remove from the open
3✔
3074
        // channel state, remove from the graph, remove from the contract
3✔
3075
        // court. Between any step it's possible that the users restarts the
3✔
3076
        // process all over again. As a result, each of the steps below are
3✔
3077
        // intended to be idempotent.
3✔
3078
        err = r.server.chanStateDB.AbandonChannel(chanPoint, bestHeight)
3✔
3079
        if err != nil {
3✔
3080
                return err
×
3081
        }
×
3082
        err = abandonChanFromGraph(r.server.graphDB, chanPoint)
3✔
3083
        if err != nil {
3✔
3084
                return err
×
3085
        }
×
3086
        err = r.server.chainArb.ResolveContract(*chanPoint)
3✔
3087
        if err != nil {
3✔
3088
                return err
×
3089
        }
×
3090

3091
        // If this channel was in the process of being closed, but didn't fully
3092
        // close, then it's possible that the nursery is hanging on to some
3093
        // state. To err on the side of caution, we'll now attempt to wipe any
3094
        // state for this channel from the nursery.
3095
        err = r.server.utxoNursery.RemoveChannel(chanPoint)
3✔
3096
        if err != nil && err != contractcourt.ErrContractNotFound {
3✔
3097
                return err
×
3098
        }
×
3099

3100
        // Finally, notify the backup listeners that the channel can be removed
3101
        // from any channel backups.
3102
        r.server.channelNotifier.NotifyClosedChannelEvent(*chanPoint)
3✔
3103

3✔
3104
        return nil
3✔
3105
}
3106

3107
// AbandonChannel removes all channel state from the database except for a
3108
// close summary. This method can be used to get rid of permanently unusable
3109
// channels due to bugs fixed in newer versions of lnd.
3110
func (r *rpcServer) AbandonChannel(_ context.Context,
3111
        in *lnrpc.AbandonChannelRequest) (*lnrpc.AbandonChannelResponse, error) {
3✔
3112

3✔
3113
        // If this isn't the dev build, then we won't allow the RPC to be
3✔
3114
        // executed, as it's an advanced feature and won't be activated in
3✔
3115
        // regular production/release builds except for the explicit case of
3✔
3116
        // externally funded channels that are still pending. Due to repeated
3✔
3117
        // requests, we also allow this requirement to be overwritten by a new
3✔
3118
        // flag that attests to the user knowing what they're doing and the risk
3✔
3119
        // associated with the command/RPC.
3✔
3120
        if !in.IKnowWhatIAmDoing && !in.PendingFundingShimOnly &&
3✔
3121
                !build.IsDevBuild() {
3✔
3122

×
3123
                return nil, fmt.Errorf("AbandonChannel RPC call only " +
×
3124
                        "available in dev builds")
×
3125
        }
×
3126

3127
        // We'll parse out the arguments to we can obtain the chanPoint of the
3128
        // target channel.
3129
        txid, err := lnrpc.GetChanPointFundingTxid(in.GetChannelPoint())
3✔
3130
        if err != nil {
3✔
3131
                return nil, err
×
3132
        }
×
3133
        index := in.ChannelPoint.OutputIndex
3✔
3134
        chanPoint := wire.NewOutPoint(txid, index)
3✔
3135

3✔
3136
        // When we remove the channel from the database, we need to set a close
3✔
3137
        // height, so we'll just use the current best known height.
3✔
3138
        _, bestHeight, err := r.server.cc.ChainIO.GetBestBlock()
3✔
3139
        if err != nil {
3✔
3140
                return nil, err
×
3141
        }
×
3142

3143
        dbChan, err := r.server.chanStateDB.FetchChannel(*chanPoint)
3✔
3144
        switch {
3✔
3145
        // If the channel isn't found in the set of open channels, then we can
3146
        // continue on as it can't be loaded into the link/peer.
3147
        case err == channeldb.ErrChannelNotFound:
3✔
3148
                break
3✔
3149

3150
        // If the channel is still known to be open, then before we modify any
3151
        // on-disk state, we'll remove the channel from the switch and peer
3152
        // state if it's been loaded in.
3153
        case err == nil:
3✔
3154
                // If the user requested the more safe version that only allows
3✔
3155
                // the removal of externally (shim) funded channels that are
3✔
3156
                // still pending, we enforce this option now that we know the
3✔
3157
                // state of the channel.
3✔
3158
                //
3✔
3159
                // TODO(guggero): Properly store the funding type (wallet, shim,
3✔
3160
                // PSBT) on the channel so we don't need to use the thaw height.
3✔
3161
                isShimFunded := dbChan.ThawHeight > 0
3✔
3162
                isPendingShimFunded := isShimFunded && dbChan.IsPending
3✔
3163
                if !in.IKnowWhatIAmDoing && in.PendingFundingShimOnly &&
3✔
3164
                        !isPendingShimFunded {
3✔
3165

×
3166
                        return nil, fmt.Errorf("channel %v is not externally "+
×
3167
                                "funded or not pending", chanPoint)
×
3168
                }
×
3169

3170
                // We'll mark the channel as borked before we remove the state
3171
                // from the switch/peer so it won't be loaded back in if the
3172
                // peer reconnects.
3173
                if err := dbChan.MarkBorked(); err != nil {
3✔
3174
                        return nil, err
×
3175
                }
×
3176
                remotePub := dbChan.IdentityPub
3✔
3177
                if peer, err := r.server.FindPeer(remotePub); err == nil {
6✔
3178
                        peer.WipeChannel(chanPoint)
3✔
3179
                }
3✔
3180

3181
        default:
×
3182
                return nil, err
×
3183
        }
3184

3185
        // Remove the channel from the graph, database and contract court.
3186
        if err := r.abandonChan(chanPoint, uint32(bestHeight)); err != nil {
3✔
3187
                return nil, err
×
3188
        }
×
3189

3190
        return &lnrpc.AbandonChannelResponse{
3✔
3191
                Status: fmt.Sprintf("channel %v abandoned", chanPoint.String()),
3✔
3192
        }, nil
3✔
3193
}
3194

3195
// GetInfo returns general information concerning the lightning node including
3196
// its identity pubkey, alias, the chains it is connected to, and information
3197
// concerning the number of open+pending channels.
3198
func (r *rpcServer) GetInfo(_ context.Context,
3199
        _ *lnrpc.GetInfoRequest) (*lnrpc.GetInfoResponse, error) {
3✔
3200

3✔
3201
        serverPeers := r.server.Peers()
3✔
3202

3✔
3203
        openChannels, err := r.server.chanStateDB.FetchAllOpenChannels()
3✔
3204
        if err != nil {
3✔
3205
                return nil, err
×
3206
        }
×
3207

3208
        var activeChannels uint32
3✔
3209
        for _, channel := range openChannels {
6✔
3210
                chanID := lnwire.NewChanIDFromOutPoint(channel.FundingOutpoint)
3✔
3211
                if r.server.htlcSwitch.HasActiveLink(chanID) {
6✔
3212
                        activeChannels++
3✔
3213
                }
3✔
3214
        }
3215

3216
        inactiveChannels := uint32(len(openChannels)) - activeChannels
3✔
3217

3✔
3218
        pendingChannels, err := r.server.chanStateDB.FetchPendingChannels()
3✔
3219
        if err != nil {
3✔
3220
                return nil, fmt.Errorf("unable to get retrieve pending "+
×
3221
                        "channels: %v", err)
×
3222
        }
×
3223
        nPendingChannels := uint32(len(pendingChannels))
3✔
3224

3✔
3225
        idPub := r.server.identityECDH.PubKey().SerializeCompressed()
3✔
3226
        encodedIDPub := hex.EncodeToString(idPub)
3✔
3227

3✔
3228
        bestHash, bestHeight, err := r.server.cc.ChainIO.GetBestBlock()
3✔
3229
        if err != nil {
3✔
3230
                return nil, fmt.Errorf("unable to get best block info: %w", err)
×
3231
        }
×
3232

3233
        isSynced, bestHeaderTimestamp, err := r.server.cc.Wallet.IsSynced()
3✔
3234
        if err != nil {
3✔
3235
                return nil, fmt.Errorf("unable to sync PoV of the wallet "+
×
3236
                        "with current best block in the main chain: %v", err)
×
3237
        }
×
3238

3239
        // If the router does full channel validation, it has a lot of work to
3240
        // do for each block. So it might be possible that it isn't yet up to
3241
        // date with the most recent block, even if the wallet is. This can
3242
        // happen in environments with high CPU load (such as parallel itests).
3243
        // Since the `synced_to_chain` flag in the response of this call is used
3244
        // by many wallets (and also our itests) to make sure everything's up to
3245
        // date, we add the router's state to it. So the flag will only toggle
3246
        // to true once the router was also able to catch up.
3247
        if !r.cfg.Routing.AssumeChannelValid {
6✔
3248
                routerHeight := r.server.graphBuilder.SyncedHeight()
3✔
3249
                isSynced = isSynced && uint32(bestHeight) == routerHeight
3✔
3250
        }
3✔
3251

3252
        network := lncfg.NormalizeNetwork(r.cfg.ActiveNetParams.Name)
3✔
3253
        activeChains := []*lnrpc.Chain{
3✔
3254
                {
3✔
3255
                        Chain:   BitcoinChainName,
3✔
3256
                        Network: network,
3✔
3257
                },
3✔
3258
        }
3✔
3259

3✔
3260
        // Check if external IP addresses were provided to lnd and use them
3✔
3261
        // to set the URIs.
3✔
3262
        nodeAnn := r.server.getNodeAnnouncement()
3✔
3263

3✔
3264
        addrs := nodeAnn.Addresses
3✔
3265
        uris := make([]string, len(addrs))
3✔
3266
        for i, addr := range addrs {
6✔
3267
                uris[i] = fmt.Sprintf("%s@%s", encodedIDPub, addr.String())
3✔
3268
        }
3✔
3269

3270
        isGraphSynced := r.server.authGossiper.SyncManager().IsGraphSynced()
3✔
3271

3✔
3272
        features := make(map[uint32]*lnrpc.Feature)
3✔
3273
        sets := r.server.featureMgr.ListSets()
3✔
3274

3✔
3275
        for _, set := range sets {
6✔
3276
                // Get the a list of lnrpc features for each set we support.
3✔
3277
                featureVector := r.server.featureMgr.Get(set)
3✔
3278
                rpcFeatures := invoicesrpc.CreateRPCFeatures(featureVector)
3✔
3279

3✔
3280
                // Add the features to our map of features, allowing over writing of
3✔
3281
                // existing values because features in different sets with the same bit
3✔
3282
                // are duplicated across sets.
3✔
3283
                for bit, feature := range rpcFeatures {
6✔
3284
                        features[bit] = feature
3✔
3285
                }
3✔
3286
        }
3287

3288
        // TODO(roasbeef): add synced height n stuff
3289

3290
        isTestNet := chainreg.IsTestnet(&r.cfg.ActiveNetParams)
3✔
3291
        nodeColor := graph.EncodeHexColor(nodeAnn.RGBColor)
3✔
3292
        version := build.Version() + " commit=" + build.Commit
3✔
3293

3✔
3294
        return &lnrpc.GetInfoResponse{
3✔
3295
                IdentityPubkey:            encodedIDPub,
3✔
3296
                NumPendingChannels:        nPendingChannels,
3✔
3297
                NumActiveChannels:         activeChannels,
3✔
3298
                NumInactiveChannels:       inactiveChannels,
3✔
3299
                NumPeers:                  uint32(len(serverPeers)),
3✔
3300
                BlockHeight:               uint32(bestHeight),
3✔
3301
                BlockHash:                 bestHash.String(),
3✔
3302
                SyncedToChain:             isSynced,
3✔
3303
                Testnet:                   isTestNet,
3✔
3304
                Chains:                    activeChains,
3✔
3305
                Uris:                      uris,
3✔
3306
                Alias:                     nodeAnn.Alias.String(),
3✔
3307
                Color:                     nodeColor,
3✔
3308
                BestHeaderTimestamp:       bestHeaderTimestamp,
3✔
3309
                Version:                   version,
3✔
3310
                CommitHash:                build.CommitHash,
3✔
3311
                SyncedToGraph:             isGraphSynced,
3✔
3312
                Features:                  features,
3✔
3313
                RequireHtlcInterceptor:    r.cfg.RequireInterceptor,
3✔
3314
                StoreFinalHtlcResolutions: r.cfg.StoreFinalHtlcResolutions,
3✔
3315
        }, nil
3✔
3316
}
3317

3318
// GetDebugInfo returns debug information concerning the state of the daemon
3319
// and its subsystems. This includes the full configuration and the latest log
3320
// entries from the log file.
3321
func (r *rpcServer) GetDebugInfo(_ context.Context,
3322
        _ *lnrpc.GetDebugInfoRequest) (*lnrpc.GetDebugInfoResponse, error) {
×
3323

×
3324
        flatConfig, _, err := configToFlatMap(*r.cfg)
×
3325
        if err != nil {
×
3326
                return nil, fmt.Errorf("error converting config to flat map: "+
×
3327
                        "%w", err)
×
3328
        }
×
3329

3330
        logFileName := filepath.Join(r.cfg.LogDir, defaultLogFilename)
×
3331
        logContent, err := os.ReadFile(logFileName)
×
3332
        if err != nil {
×
3333
                return nil, fmt.Errorf("error reading log file '%s': %w",
×
3334
                        logFileName, err)
×
3335
        }
×
3336

3337
        return &lnrpc.GetDebugInfoResponse{
×
3338
                Config: flatConfig,
×
3339
                Log:    strings.Split(string(logContent), "\n"),
×
3340
        }, nil
×
3341
}
3342

3343
// GetRecoveryInfo returns a boolean indicating whether the wallet is started
3344
// in recovery mode, whether the recovery is finished, and the progress made
3345
// so far.
3346
func (r *rpcServer) GetRecoveryInfo(ctx context.Context,
3347
        in *lnrpc.GetRecoveryInfoRequest) (*lnrpc.GetRecoveryInfoResponse, error) {
3✔
3348

3✔
3349
        isRecoveryMode, progress, err := r.server.cc.Wallet.GetRecoveryInfo()
3✔
3350
        if err != nil {
3✔
3351
                return nil, fmt.Errorf("unable to get wallet recovery info: %w",
×
3352
                        err)
×
3353
        }
×
3354

3355
        rpcsLog.Debugf("[getrecoveryinfo] is recovery mode=%v, progress=%v",
3✔
3356
                isRecoveryMode, progress)
3✔
3357

3✔
3358
        return &lnrpc.GetRecoveryInfoResponse{
3✔
3359
                RecoveryMode:     isRecoveryMode,
3✔
3360
                RecoveryFinished: progress == 1,
3✔
3361
                Progress:         progress,
3✔
3362
        }, nil
3✔
3363
}
3364

3365
// ListPeers returns a verbose listing of all currently active peers.
3366
func (r *rpcServer) ListPeers(ctx context.Context,
3367
        in *lnrpc.ListPeersRequest) (*lnrpc.ListPeersResponse, error) {
3✔
3368

3✔
3369
        serverPeers := r.server.Peers()
3✔
3370
        resp := &lnrpc.ListPeersResponse{
3✔
3371
                Peers: make([]*lnrpc.Peer, 0, len(serverPeers)),
3✔
3372
        }
3✔
3373

3✔
3374
        for _, serverPeer := range serverPeers {
6✔
3375
                var (
3✔
3376
                        satSent int64
3✔
3377
                        satRecv int64
3✔
3378
                )
3✔
3379

3✔
3380
                // In order to display the total number of satoshis of outbound
3✔
3381
                // (sent) and inbound (recv'd) satoshis that have been
3✔
3382
                // transported through this peer, we'll sum up the sent/recv'd
3✔
3383
                // values for each of the active channels we have with the
3✔
3384
                // peer.
3✔
3385
                chans := serverPeer.ChannelSnapshots()
3✔
3386
                for _, c := range chans {
6✔
3387
                        satSent += int64(c.TotalMSatSent.ToSatoshis())
3✔
3388
                        satRecv += int64(c.TotalMSatReceived.ToSatoshis())
3✔
3389
                }
3✔
3390

3391
                nodePub := serverPeer.PubKey()
3✔
3392

3✔
3393
                // Retrieve the peer's sync type. If we don't currently have a
3✔
3394
                // syncer for the peer, then we'll default to a passive sync.
3✔
3395
                // This can happen if the RPC is called while a peer is
3✔
3396
                // initializing.
3✔
3397
                syncer, ok := r.server.authGossiper.SyncManager().GossipSyncer(
3✔
3398
                        nodePub,
3✔
3399
                )
3✔
3400

3✔
3401
                var lnrpcSyncType lnrpc.Peer_SyncType
3✔
3402
                if !ok {
3✔
3403
                        rpcsLog.Warnf("Gossip syncer for peer=%x not found",
×
3404
                                nodePub)
×
3405
                        lnrpcSyncType = lnrpc.Peer_UNKNOWN_SYNC
×
3406
                } else {
3✔
3407
                        syncType := syncer.SyncType()
3✔
3408
                        switch syncType {
3✔
3409
                        case discovery.ActiveSync:
3✔
3410
                                lnrpcSyncType = lnrpc.Peer_ACTIVE_SYNC
3✔
3411
                        case discovery.PassiveSync:
3✔
3412
                                lnrpcSyncType = lnrpc.Peer_PASSIVE_SYNC
3✔
3413
                        case discovery.PinnedSync:
3✔
3414
                                lnrpcSyncType = lnrpc.Peer_PINNED_SYNC
3✔
3415
                        default:
×
3416
                                return nil, fmt.Errorf("unhandled sync type %v",
×
3417
                                        syncType)
×
3418
                        }
3419
                }
3420

3421
                features := invoicesrpc.CreateRPCFeatures(
3✔
3422
                        serverPeer.RemoteFeatures(),
3✔
3423
                )
3✔
3424

3✔
3425
                rpcPeer := &lnrpc.Peer{
3✔
3426
                        PubKey:          hex.EncodeToString(nodePub[:]),
3✔
3427
                        Address:         serverPeer.Conn().RemoteAddr().String(),
3✔
3428
                        Inbound:         serverPeer.Inbound(),
3✔
3429
                        BytesRecv:       serverPeer.BytesReceived(),
3✔
3430
                        BytesSent:       serverPeer.BytesSent(),
3✔
3431
                        SatSent:         satSent,
3✔
3432
                        SatRecv:         satRecv,
3✔
3433
                        PingTime:        serverPeer.PingTime(),
3✔
3434
                        SyncType:        lnrpcSyncType,
3✔
3435
                        Features:        features,
3✔
3436
                        LastPingPayload: serverPeer.LastRemotePingPayload(),
3✔
3437
                }
3✔
3438

3✔
3439
                var peerErrors []interface{}
3✔
3440

3✔
3441
                // If we only want the most recent error, get the most recent
3✔
3442
                // error from the buffer and add it to our list of errors if
3✔
3443
                // it is non-nil. If we want all the stored errors, simply
3✔
3444
                // add the full list to our set of errors.
3✔
3445
                if in.LatestError {
3✔
3446
                        latestErr := serverPeer.ErrorBuffer().Latest()
×
3447
                        if latestErr != nil {
×
3448
                                peerErrors = []interface{}{latestErr}
×
3449
                        }
×
3450
                } else {
3✔
3451
                        peerErrors = serverPeer.ErrorBuffer().List()
3✔
3452
                }
3✔
3453

3454
                // Add the relevant peer errors to our response.
3455
                for _, error := range peerErrors {
6✔
3456
                        tsError := error.(*peer.TimestampedError)
3✔
3457

3✔
3458
                        rpcErr := &lnrpc.TimestampedError{
3✔
3459
                                Timestamp: uint64(tsError.Timestamp.Unix()),
3✔
3460
                                Error:     tsError.Error.Error(),
3✔
3461
                        }
3✔
3462

3✔
3463
                        rpcPeer.Errors = append(rpcPeer.Errors, rpcErr)
3✔
3464
                }
3✔
3465

3466
                // If the server has started, we can query the event store
3467
                // for our peer's flap count. If we do so when the server has
3468
                // not started, the request will block.
3469
                if r.server.Started() {
6✔
3470
                        vertex, err := route.NewVertexFromBytes(nodePub[:])
3✔
3471
                        if err != nil {
3✔
3472
                                return nil, err
×
3473
                        }
×
3474

3475
                        flap, ts, err := r.server.chanEventStore.FlapCount(
3✔
3476
                                vertex,
3✔
3477
                        )
3✔
3478
                        if err != nil {
3✔
3479
                                return nil, err
×
3480
                        }
×
3481

3482
                        // If our timestamp is non-nil, we have values for our
3483
                        // peer's flap count, so we set them.
3484
                        if ts != nil {
6✔
3485
                                rpcPeer.FlapCount = int32(flap)
3✔
3486
                                rpcPeer.LastFlapNs = ts.UnixNano()
3✔
3487
                        }
3✔
3488
                }
3489

3490
                resp.Peers = append(resp.Peers, rpcPeer)
3✔
3491
        }
3492

3493
        rpcsLog.Debugf("[listpeers] yielded %v peers", serverPeers)
3✔
3494

3✔
3495
        return resp, nil
3✔
3496
}
3497

3498
// SubscribePeerEvents returns a uni-directional stream (server -> client)
3499
// for notifying the client of peer online and offline events.
3500
func (r *rpcServer) SubscribePeerEvents(req *lnrpc.PeerEventSubscription,
3501
        eventStream lnrpc.Lightning_SubscribePeerEventsServer) error {
3✔
3502

3✔
3503
        peerEventSub, err := r.server.peerNotifier.SubscribePeerEvents()
3✔
3504
        if err != nil {
3✔
3505
                return err
×
3506
        }
×
3507
        defer peerEventSub.Cancel()
3✔
3508

3✔
3509
        for {
6✔
3510
                select {
3✔
3511
                // A new update has been sent by the peer notifier, we'll
3512
                // marshal it into the form expected by the gRPC client, then
3513
                // send it off to the client.
3514
                case e := <-peerEventSub.Updates():
3✔
3515
                        var event *lnrpc.PeerEvent
3✔
3516

3✔
3517
                        switch peerEvent := e.(type) {
3✔
3518
                        case peernotifier.PeerOfflineEvent:
3✔
3519
                                event = &lnrpc.PeerEvent{
3✔
3520
                                        PubKey: hex.EncodeToString(peerEvent.PubKey[:]),
3✔
3521
                                        Type:   lnrpc.PeerEvent_PEER_OFFLINE,
3✔
3522
                                }
3✔
3523

3524
                        case peernotifier.PeerOnlineEvent:
×
3525
                                event = &lnrpc.PeerEvent{
×
3526
                                        PubKey: hex.EncodeToString(peerEvent.PubKey[:]),
×
3527
                                        Type:   lnrpc.PeerEvent_PEER_ONLINE,
×
3528
                                }
×
3529

3530
                        default:
×
3531
                                return fmt.Errorf("unexpected peer event: %v", event)
×
3532
                        }
3533

3534
                        if err := eventStream.Send(event); err != nil {
3✔
3535
                                return err
×
3536
                        }
×
3537

3538
                // The response stream's context for whatever reason has been
3539
                // closed. If context is closed by an exceeded deadline we will
3540
                // return an error.
3541
                case <-eventStream.Context().Done():
3✔
3542
                        if errors.Is(eventStream.Context().Err(), context.Canceled) {
6✔
3543
                                return nil
3✔
3544
                        }
3✔
3545
                        return eventStream.Context().Err()
×
3546

3547
                case <-r.quit:
×
3548
                        return nil
×
3549
                }
3550
        }
3551
}
3552

3553
// WalletBalance returns total unspent outputs(confirmed and unconfirmed), all
3554
// confirmed unspent outputs and all unconfirmed unspent outputs under control
3555
// by the wallet. This method can be modified by having the request specify
3556
// only witness outputs should be factored into the final output sum.
3557
// TODO(roasbeef): add async hooks into wallet balance changes.
3558
func (r *rpcServer) WalletBalance(ctx context.Context,
3559
        in *lnrpc.WalletBalanceRequest) (*lnrpc.WalletBalanceResponse, error) {
3✔
3560

3✔
3561
        // Retrieve all existing wallet accounts. We'll compute the confirmed
3✔
3562
        // and unconfirmed balance for each and tally them up.
3✔
3563
        accounts, err := r.server.cc.Wallet.ListAccounts(in.Account, nil)
3✔
3564
        if err != nil {
3✔
3565
                return nil, err
×
3566
        }
×
3567

3568
        var totalBalance, confirmedBalance, unconfirmedBalance btcutil.Amount
3✔
3569
        rpcAccountBalances := make(
3✔
3570
                map[string]*lnrpc.WalletAccountBalance, len(accounts),
3✔
3571
        )
3✔
3572
        for _, account := range accounts {
6✔
3573
                // There are two default accounts, one for NP2WKH outputs and
3✔
3574
                // another for P2WKH outputs. The balance will be computed for
3✔
3575
                // both given one call to ConfirmedBalance with the default
3✔
3576
                // wallet and imported account, so we'll skip the second
3✔
3577
                // instance to avoid inflating the balance.
3✔
3578
                switch account.AccountName {
3✔
3579
                case waddrmgr.ImportedAddrAccountName:
3✔
3580
                        // Omit the imported account from the response unless we
3✔
3581
                        // actually have any keys imported.
3✔
3582
                        if account.ImportedKeyCount == 0 {
6✔
3583
                                continue
3✔
3584
                        }
3585

3586
                        fallthrough
3✔
3587

3588
                case lnwallet.DefaultAccountName:
3✔
3589
                        if _, ok := rpcAccountBalances[account.AccountName]; ok {
6✔
3590
                                continue
3✔
3591
                        }
3592

3593
                default:
3✔
3594
                }
3595

3596
                // There now also are the accounts for the internal channel
3597
                // related keys. We skip those as they'll never have any direct
3598
                // balance.
3599
                if account.KeyScope.Purpose == keychain.BIP0043Purpose {
6✔
3600
                        continue
3✔
3601
                }
3602

3603
                // Get total balance, from txs that have >= 0 confirmations.
3604
                totalBal, err := r.server.cc.Wallet.ConfirmedBalance(
3✔
3605
                        0, account.AccountName,
3✔
3606
                )
3✔
3607
                if err != nil {
3✔
3608
                        return nil, err
×
3609
                }
×
3610
                totalBalance += totalBal
3✔
3611

3✔
3612
                // Get confirmed balance, from txs that have >= 1 confirmations.
3✔
3613
                // TODO(halseth): get both unconfirmed and confirmed balance in
3✔
3614
                // one call, as this is racy.
3✔
3615
                if in.MinConfs <= 0 {
6✔
3616
                        in.MinConfs = 1
3✔
3617
                }
3✔
3618
                confirmedBal, err := r.server.cc.Wallet.ConfirmedBalance(
3✔
3619
                        in.MinConfs, account.AccountName,
3✔
3620
                )
3✔
3621
                if err != nil {
3✔
3622
                        return nil, err
×
3623
                }
×
3624
                confirmedBalance += confirmedBal
3✔
3625

3✔
3626
                // Get unconfirmed balance, from txs with 0 confirmations.
3✔
3627
                unconfirmedBal := totalBal - confirmedBal
3✔
3628
                unconfirmedBalance += unconfirmedBal
3✔
3629

3✔
3630
                rpcAccountBalances[account.AccountName] = &lnrpc.WalletAccountBalance{
3✔
3631
                        ConfirmedBalance:   int64(confirmedBal),
3✔
3632
                        UnconfirmedBalance: int64(unconfirmedBal),
3✔
3633
                }
3✔
3634
        }
3635

3636
        // Now that we have the base balance accounted for with each account,
3637
        // we'll look at the set of locked UTXOs to tally that as well. If we
3638
        // don't display this, then anytime we attempt a funding reservation,
3639
        // the outputs will chose as being "gone" until they're confirmed on
3640
        // chain.
3641
        var lockedBalance btcutil.Amount
3✔
3642
        leases, err := r.server.cc.Wallet.ListLeasedOutputs()
3✔
3643
        if err != nil {
3✔
3644
                return nil, err
×
3645
        }
×
3646
        for _, leasedOutput := range leases {
6✔
3647
                lockedBalance += btcutil.Amount(leasedOutput.Value)
3✔
3648
        }
3✔
3649

3650
        // Get the current number of non-private anchor channels.
3651
        currentNumAnchorChans, err := r.server.cc.Wallet.CurrentNumAnchorChans()
3✔
3652
        if err != nil {
3✔
3653
                return nil, err
×
3654
        }
×
3655

3656
        // Get the required reserve for the wallet.
3657
        requiredReserve := r.server.cc.Wallet.RequiredReserve(
3✔
3658
                uint32(currentNumAnchorChans),
3✔
3659
        )
3✔
3660

3✔
3661
        rpcsLog.Debugf("[walletbalance] Total balance=%v (confirmed=%v, "+
3✔
3662
                "unconfirmed=%v)", totalBalance, confirmedBalance,
3✔
3663
                unconfirmedBalance)
3✔
3664

3✔
3665
        return &lnrpc.WalletBalanceResponse{
3✔
3666
                TotalBalance:              int64(totalBalance),
3✔
3667
                ConfirmedBalance:          int64(confirmedBalance),
3✔
3668
                UnconfirmedBalance:        int64(unconfirmedBalance),
3✔
3669
                LockedBalance:             int64(lockedBalance),
3✔
3670
                ReservedBalanceAnchorChan: int64(requiredReserve),
3✔
3671
                AccountBalance:            rpcAccountBalances,
3✔
3672
        }, nil
3✔
3673
}
3674

3675
// ChannelBalance returns the total available channel flow across all open
3676
// channels in satoshis.
3677
func (r *rpcServer) ChannelBalance(ctx context.Context,
3678
        in *lnrpc.ChannelBalanceRequest) (
3679
        *lnrpc.ChannelBalanceResponse, error) {
3✔
3680

3✔
3681
        var (
3✔
3682
                localBalance             lnwire.MilliSatoshi
3✔
3683
                remoteBalance            lnwire.MilliSatoshi
3✔
3684
                unsettledLocalBalance    lnwire.MilliSatoshi
3✔
3685
                unsettledRemoteBalance   lnwire.MilliSatoshi
3✔
3686
                pendingOpenLocalBalance  lnwire.MilliSatoshi
3✔
3687
                pendingOpenRemoteBalance lnwire.MilliSatoshi
3✔
3688
                customDataBuf            bytes.Buffer
3✔
3689
        )
3✔
3690

3✔
3691
        openChannels, err := r.server.chanStateDB.FetchAllOpenChannels()
3✔
3692
        if err != nil {
3✔
3693
                return nil, err
×
3694
        }
×
3695

3696
        // Encode the number of open channels to the custom data buffer.
3697
        err = wire.WriteVarInt(&customDataBuf, 0, uint64(len(openChannels)))
3✔
3698
        if err != nil {
3✔
3699
                return nil, err
×
3700
        }
×
3701

3702
        for _, channel := range openChannels {
6✔
3703
                c := channel.LocalCommitment
3✔
3704
                localBalance += c.LocalBalance
3✔
3705
                remoteBalance += c.RemoteBalance
3✔
3706

3✔
3707
                // Add pending htlc amount.
3✔
3708
                for _, htlc := range c.Htlcs {
6✔
3709
                        if htlc.Incoming {
6✔
3710
                                unsettledLocalBalance += htlc.Amt
3✔
3711
                        } else {
6✔
3712
                                unsettledRemoteBalance += htlc.Amt
3✔
3713
                        }
3✔
3714
                }
3715

3716
                // Encode the custom data for this open channel.
3717
                openChanData := channel.LocalCommitment.CustomBlob.UnwrapOr(nil)
3✔
3718
                err = wire.WriteVarBytes(&customDataBuf, 0, openChanData)
3✔
3719
                if err != nil {
3✔
3720
                        return nil, err
×
3721
                }
×
3722
        }
3723

3724
        pendingChannels, err := r.server.chanStateDB.FetchPendingChannels()
3✔
3725
        if err != nil {
3✔
3726
                return nil, err
×
3727
        }
×
3728

3729
        // Encode the number of pending channels to the custom data buffer.
3730
        err = wire.WriteVarInt(&customDataBuf, 0, uint64(len(pendingChannels)))
3✔
3731
        if err != nil {
3✔
3732
                return nil, err
×
3733
        }
×
3734

3735
        for _, channel := range pendingChannels {
6✔
3736
                c := channel.LocalCommitment
3✔
3737
                pendingOpenLocalBalance += c.LocalBalance
3✔
3738
                pendingOpenRemoteBalance += c.RemoteBalance
3✔
3739

3✔
3740
                // Encode the custom data for this pending channel.
3✔
3741
                openChanData := channel.LocalCommitment.CustomBlob.UnwrapOr(nil)
3✔
3742
                err = wire.WriteVarBytes(&customDataBuf, 0, openChanData)
3✔
3743
                if err != nil {
3✔
3744
                        return nil, err
×
3745
                }
×
3746
        }
3747

3748
        rpcsLog.Debugf("[channelbalance] local_balance=%v remote_balance=%v "+
3✔
3749
                "unsettled_local_balance=%v unsettled_remote_balance=%v "+
3✔
3750
                "pending_open_local_balance=%v pending_open_remote_balance=%v",
3✔
3751
                localBalance, remoteBalance, unsettledLocalBalance,
3✔
3752
                unsettledRemoteBalance, pendingOpenLocalBalance,
3✔
3753
                pendingOpenRemoteBalance)
3✔
3754

3✔
3755
        resp := &lnrpc.ChannelBalanceResponse{
3✔
3756
                LocalBalance: &lnrpc.Amount{
3✔
3757
                        Sat:  uint64(localBalance.ToSatoshis()),
3✔
3758
                        Msat: uint64(localBalance),
3✔
3759
                },
3✔
3760
                RemoteBalance: &lnrpc.Amount{
3✔
3761
                        Sat:  uint64(remoteBalance.ToSatoshis()),
3✔
3762
                        Msat: uint64(remoteBalance),
3✔
3763
                },
3✔
3764
                UnsettledLocalBalance: &lnrpc.Amount{
3✔
3765
                        Sat:  uint64(unsettledLocalBalance.ToSatoshis()),
3✔
3766
                        Msat: uint64(unsettledLocalBalance),
3✔
3767
                },
3✔
3768
                UnsettledRemoteBalance: &lnrpc.Amount{
3✔
3769
                        Sat:  uint64(unsettledRemoteBalance.ToSatoshis()),
3✔
3770
                        Msat: uint64(unsettledRemoteBalance),
3✔
3771
                },
3✔
3772
                PendingOpenLocalBalance: &lnrpc.Amount{
3✔
3773
                        Sat:  uint64(pendingOpenLocalBalance.ToSatoshis()),
3✔
3774
                        Msat: uint64(pendingOpenLocalBalance),
3✔
3775
                },
3✔
3776
                PendingOpenRemoteBalance: &lnrpc.Amount{
3✔
3777
                        Sat:  uint64(pendingOpenRemoteBalance.ToSatoshis()),
3✔
3778
                        Msat: uint64(pendingOpenRemoteBalance),
3✔
3779
                },
3✔
3780
                CustomChannelData: customDataBuf.Bytes(),
3✔
3781

3✔
3782
                // Deprecated fields.
3✔
3783
                Balance:            int64(localBalance.ToSatoshis()),
3✔
3784
                PendingOpenBalance: int64(pendingOpenLocalBalance.ToSatoshis()),
3✔
3785
        }
3✔
3786

3✔
3787
        err = fn.MapOptionZ(
3✔
3788
                r.server.implCfg.AuxDataParser,
3✔
3789
                func(parser AuxDataParser) error {
3✔
3790
                        return parser.InlineParseCustomData(resp)
×
3791
                },
×
3792
        )
3793
        if err != nil {
3✔
3794
                return nil, fmt.Errorf("error parsing custom data: %w", err)
×
3795
        }
×
3796

3797
        return resp, nil
3✔
3798
}
3799

3800
type (
3801
        pendingOpenChannels  []*lnrpc.PendingChannelsResponse_PendingOpenChannel
3802
        pendingForceClose    []*lnrpc.PendingChannelsResponse_ForceClosedChannel
3803
        waitingCloseChannels []*lnrpc.PendingChannelsResponse_WaitingCloseChannel
3804
)
3805

3806
// fetchPendingOpenChannels queries the database for a list of channels that
3807
// have pending open state. The returned result is used in the response of the
3808
// PendingChannels RPC.
3809
func (r *rpcServer) fetchPendingOpenChannels() (pendingOpenChannels, error) {
3✔
3810
        // First, we'll populate the response with all the channels that are
3✔
3811
        // soon to be opened. We can easily fetch this data from the database
3✔
3812
        // and map the db struct to the proto response.
3✔
3813
        channels, err := r.server.chanStateDB.FetchPendingChannels()
3✔
3814
        if err != nil {
3✔
3815
                rpcsLog.Errorf("unable to fetch pending channels: %v", err)
×
3816
                return nil, err
×
3817
        }
×
3818

3819
        _, currentHeight, err := r.server.cc.ChainIO.GetBestBlock()
3✔
3820
        if err != nil {
3✔
3821
                return nil, err
×
3822
        }
×
3823

3824
        result := make(pendingOpenChannels, len(channels))
3✔
3825
        for i, pendingChan := range channels {
6✔
3826
                pub := pendingChan.IdentityPub.SerializeCompressed()
3✔
3827

3✔
3828
                // As this is required for display purposes, we'll calculate
3✔
3829
                // the weight of the commitment transaction. We also add on the
3✔
3830
                // estimated weight of the witness to calculate the weight of
3✔
3831
                // the transaction if it were to be immediately unilaterally
3✔
3832
                // broadcast.
3✔
3833
                // TODO(roasbeef): query for funding tx from wallet, display
3✔
3834
                // that also?
3✔
3835
                var witnessWeight int64
3✔
3836
                if pendingChan.ChanType.IsTaproot() {
6✔
3837
                        witnessWeight = input.TaprootKeyPathWitnessSize
3✔
3838
                } else {
6✔
3839
                        witnessWeight = input.WitnessCommitmentTxWeight
3✔
3840
                }
3✔
3841

3842
                localCommitment := pendingChan.LocalCommitment
3✔
3843
                utx := btcutil.NewTx(localCommitment.CommitTx)
3✔
3844
                commitBaseWeight := blockchain.GetTransactionWeight(utx)
3✔
3845
                commitWeight := commitBaseWeight + witnessWeight
3✔
3846

3✔
3847
                // FundingExpiryBlocks is the distance from the current block
3✔
3848
                // height to the broadcast height + MaxWaitNumBlocksFundingConf.
3✔
3849
                maxFundingHeight := funding.MaxWaitNumBlocksFundingConf +
3✔
3850
                        pendingChan.BroadcastHeight()
3✔
3851
                fundingExpiryBlocks := int32(maxFundingHeight) - currentHeight
3✔
3852

3✔
3853
                customChanBytes, err := encodeCustomChanData(pendingChan)
3✔
3854
                if err != nil {
3✔
3855
                        return nil, fmt.Errorf("unable to encode open chan "+
×
3856
                                "data: %w", err)
×
3857
                }
×
3858

3859
                result[i] = &lnrpc.PendingChannelsResponse_PendingOpenChannel{
3✔
3860
                        Channel: &lnrpc.PendingChannelsResponse_PendingChannel{
3✔
3861
                                RemoteNodePub:        hex.EncodeToString(pub),
3✔
3862
                                ChannelPoint:         pendingChan.FundingOutpoint.String(),
3✔
3863
                                Capacity:             int64(pendingChan.Capacity),
3✔
3864
                                LocalBalance:         int64(localCommitment.LocalBalance.ToSatoshis()),
3✔
3865
                                RemoteBalance:        int64(localCommitment.RemoteBalance.ToSatoshis()),
3✔
3866
                                LocalChanReserveSat:  int64(pendingChan.LocalChanCfg.ChanReserve),
3✔
3867
                                RemoteChanReserveSat: int64(pendingChan.RemoteChanCfg.ChanReserve),
3✔
3868
                                Initiator:            rpcInitiator(pendingChan.IsInitiator),
3✔
3869
                                CommitmentType:       rpcCommitmentType(pendingChan.ChanType),
3✔
3870
                                Private:              isPrivate(pendingChan),
3✔
3871
                                Memo:                 string(pendingChan.Memo),
3✔
3872
                                CustomChannelData:    customChanBytes,
3✔
3873
                        },
3✔
3874
                        CommitWeight:        commitWeight,
3✔
3875
                        CommitFee:           int64(localCommitment.CommitFee),
3✔
3876
                        FeePerKw:            int64(localCommitment.FeePerKw),
3✔
3877
                        FundingExpiryBlocks: fundingExpiryBlocks,
3✔
3878
                        // TODO(roasbeef): need to track confirmation height
3✔
3879
                }
3✔
3880
        }
3881

3882
        return result, nil
3✔
3883
}
3884

3885
// fetchPendingForceCloseChannels queries the database for a list of channels
3886
// that have their closing transactions confirmed but not fully resolved yet.
3887
// The returned result is used in the response of the PendingChannels RPC.
3888
func (r *rpcServer) fetchPendingForceCloseChannels() (pendingForceClose,
3889
        int64, error) {
3✔
3890

3✔
3891
        _, currentHeight, err := r.server.cc.ChainIO.GetBestBlock()
3✔
3892
        if err != nil {
3✔
3893
                return nil, 0, err
×
3894
        }
×
3895

3896
        // Next, we'll examine the channels that are soon to be closed so we
3897
        // can populate these fields within the response.
3898
        channels, err := r.server.chanStateDB.FetchClosedChannels(true)
3✔
3899
        if err != nil {
3✔
3900
                rpcsLog.Errorf("unable to fetch closed channels: %v", err)
×
3901
                return nil, 0, err
×
3902
        }
×
3903

3904
        result := make(pendingForceClose, 0)
3✔
3905
        limboBalance := int64(0)
3✔
3906

3✔
3907
        for _, pendingClose := range channels {
6✔
3908
                // First construct the channel struct itself, this will be
3✔
3909
                // needed regardless of how this channel was closed.
3✔
3910
                pub := pendingClose.RemotePub.SerializeCompressed()
3✔
3911
                chanPoint := pendingClose.ChanPoint
3✔
3912

3✔
3913
                // Create the pending channel. If this channel was closed before
3✔
3914
                // we started storing historical channel data, we will not know
3✔
3915
                // who initiated the channel, so we set the initiator field to
3✔
3916
                // unknown.
3✔
3917
                channel := &lnrpc.PendingChannelsResponse_PendingChannel{
3✔
3918
                        RemoteNodePub:  hex.EncodeToString(pub),
3✔
3919
                        ChannelPoint:   chanPoint.String(),
3✔
3920
                        Capacity:       int64(pendingClose.Capacity),
3✔
3921
                        LocalBalance:   int64(pendingClose.SettledBalance),
3✔
3922
                        CommitmentType: lnrpc.CommitmentType_UNKNOWN_COMMITMENT_TYPE,
3✔
3923
                        Initiator:      lnrpc.Initiator_INITIATOR_UNKNOWN,
3✔
3924
                }
3✔
3925

3✔
3926
                // Lookup the channel in the historical channel bucket to obtain
3✔
3927
                // initiator information. If the historical channel bucket was
3✔
3928
                // not found, or the channel itself, this channel was closed
3✔
3929
                // in a version before we started persisting historical
3✔
3930
                // channels, so we silence the error.
3✔
3931
                historical, err := r.server.chanStateDB.FetchHistoricalChannel(
3✔
3932
                        &pendingClose.ChanPoint,
3✔
3933
                )
3✔
3934
                switch err {
3✔
3935
                // If the channel was closed in a version that did not record
3936
                // historical channels, ignore the error.
3937
                case channeldb.ErrNoHistoricalBucket:
×
3938
                case channeldb.ErrChannelNotFound:
×
3939

3940
                case nil:
3✔
3941
                        channel.Initiator = rpcInitiator(historical.IsInitiator)
3✔
3942
                        channel.CommitmentType = rpcCommitmentType(
3✔
3943
                                historical.ChanType,
3✔
3944
                        )
3✔
3945

3✔
3946
                        // Get the number of forwarding packages from the
3✔
3947
                        // historical channel.
3✔
3948
                        fwdPkgs, err := historical.LoadFwdPkgs()
3✔
3949
                        if err != nil {
3✔
3950
                                rpcsLog.Errorf("unable to load forwarding "+
×
3951
                                        "packages for channel:%s, %v",
×
3952
                                        historical.ShortChannelID, err)
×
3953
                                return nil, 0, err
×
3954
                        }
×
3955
                        channel.NumForwardingPackages = int64(len(fwdPkgs))
3✔
3956

3✔
3957
                        channel.RemoteBalance = int64(
3✔
3958
                                historical.LocalCommitment.RemoteBalance.ToSatoshis(),
3✔
3959
                        )
3✔
3960

3✔
3961
                        channel.Private = isPrivate(historical)
3✔
3962
                        channel.Memo = string(historical.Memo)
3✔
3963

3964
                // If the error is non-nil, and not due to older versions of lnd
3965
                // not persisting historical channels, return it.
3966
                default:
×
3967
                        return nil, 0, err
×
3968
                }
3969

3970
                closeTXID := pendingClose.ClosingTXID.String()
3✔
3971

3✔
3972
                switch pendingClose.CloseType {
3✔
3973

3974
                // A coop closed channel should never be in the "pending close"
3975
                // state. If a node upgraded from an older lnd version in the
3976
                // middle of a their channel confirming, it will be in this
3977
                // state. We log a warning that the channel will not be included
3978
                // in the now deprecated pending close channels field.
3979
                case channeldb.CooperativeClose:
×
3980
                        rpcsLog.Warnf("channel %v cooperatively closed and "+
×
3981
                                "in pending close state",
×
3982
                                pendingClose.ChanPoint)
×
3983

3984
                // If the channel was force closed, then we'll need to query
3985
                // the utxoNursery for additional information.
3986
                // TODO(halseth): distinguish remote and local case?
3987
                case channeldb.LocalForceClose, channeldb.RemoteForceClose:
3✔
3988
                        forceClose := &lnrpc.PendingChannelsResponse_ForceClosedChannel{
3✔
3989
                                Channel:     channel,
3✔
3990
                                ClosingTxid: closeTXID,
3✔
3991
                        }
3✔
3992

3✔
3993
                        // Fetch reports from both nursery and resolvers. At the
3✔
3994
                        // moment this is not an atomic snapshot. This is
3✔
3995
                        // planned to be resolved when the nursery is removed
3✔
3996
                        // and channel arbitrator will be the single source for
3✔
3997
                        // these kind of reports.
3✔
3998
                        err := r.nurseryPopulateForceCloseResp(
3✔
3999
                                &chanPoint, currentHeight, forceClose,
3✔
4000
                        )
3✔
4001
                        if err != nil {
3✔
4002
                                rpcsLog.Errorf("unable to populate nursery "+
×
4003
                                        "force close resp:%s, %v",
×
4004
                                        chanPoint, err)
×
4005
                                return nil, 0, err
×
4006
                        }
×
4007

4008
                        err = r.arbitratorPopulateForceCloseResp(
3✔
4009
                                &chanPoint, currentHeight, forceClose,
3✔
4010
                        )
3✔
4011
                        if err != nil {
3✔
4012
                                rpcsLog.Errorf("unable to populate arbitrator "+
×
4013
                                        "force close resp:%s, %v",
×
4014
                                        chanPoint, err)
×
4015
                                return nil, 0, err
×
4016
                        }
×
4017

4018
                        limboBalance += forceClose.LimboBalance
3✔
4019
                        result = append(result, forceClose)
3✔
4020
                }
4021
        }
4022

4023
        return result, limboBalance, nil
3✔
4024
}
4025

4026
// fetchWaitingCloseChannels queries the database for a list of channels
4027
// that have their closing transactions broadcast but not confirmed yet.
4028
// The returned result is used in the response of the PendingChannels RPC.
4029
func (r *rpcServer) fetchWaitingCloseChannels(
4030
        includeRawTx bool) (waitingCloseChannels, int64, error) {
3✔
4031

3✔
4032
        // We'll also fetch all channels that are open, but have had their
3✔
4033
        // commitment broadcasted, meaning they are waiting for the closing
3✔
4034
        // transaction to confirm.
3✔
4035
        channels, err := r.server.chanStateDB.FetchWaitingCloseChannels()
3✔
4036
        if err != nil {
3✔
4037
                rpcsLog.Errorf("unable to fetch channels waiting close: %v",
×
4038
                        err)
×
4039
                return nil, 0, err
×
4040
        }
×
4041

4042
        result := make(waitingCloseChannels, 0)
3✔
4043
        limboBalance := int64(0)
3✔
4044

3✔
4045
        // getClosingTx is a helper closure that tries to find the closing tx of
3✔
4046
        // a given waiting close channel. Notice that if the remote closes the
3✔
4047
        // channel, we may not have the closing tx.
3✔
4048
        getClosingTx := func(c *channeldb.OpenChannel) (*wire.MsgTx, error) {
6✔
4049
                var (
3✔
4050
                        tx  *wire.MsgTx
3✔
4051
                        err error
3✔
4052
                )
3✔
4053

3✔
4054
                // First, we try to locate the force closing tx. If not found,
3✔
4055
                // we will then try to find its coop closing tx.
3✔
4056
                tx, err = c.BroadcastedCommitment()
3✔
4057
                if err == nil {
6✔
4058
                        return tx, nil
3✔
4059
                }
3✔
4060

4061
                // If the error returned is not ErrNoCloseTx, something
4062
                // unexpected happened and we will return the error.
4063
                if err != channeldb.ErrNoCloseTx {
3✔
4064
                        return nil, err
×
4065
                }
×
4066

4067
                // Otherwise, we continue to locate its coop closing tx.
4068
                tx, err = c.BroadcastedCooperative()
3✔
4069
                if err == nil {
6✔
4070
                        return tx, nil
3✔
4071
                }
3✔
4072

4073
                // Return the error if it's not ErrNoCloseTx.
4074
                if err != channeldb.ErrNoCloseTx {
3✔
4075
                        return nil, err
×
4076
                }
×
4077

4078
                // Otherwise return an empty tx. This can happen if the remote
4079
                // broadcast the closing tx and we haven't recorded it yet.
4080
                return nil, nil
3✔
4081
        }
4082

4083
        for _, waitingClose := range channels {
6✔
4084
                pub := waitingClose.IdentityPub.SerializeCompressed()
3✔
4085
                chanPoint := waitingClose.FundingOutpoint
3✔
4086

3✔
4087
                var commitments lnrpc.PendingChannelsResponse_Commitments
3✔
4088

3✔
4089
                // Report local commit. May not be present when DLP is active.
3✔
4090
                if waitingClose.LocalCommitment.CommitTx != nil {
6✔
4091
                        commitments.LocalTxid =
3✔
4092
                                waitingClose.LocalCommitment.CommitTx.TxHash().
3✔
4093
                                        String()
3✔
4094

3✔
4095
                        commitments.LocalCommitFeeSat = uint64(
3✔
4096
                                waitingClose.LocalCommitment.CommitFee,
3✔
4097
                        )
3✔
4098
                }
3✔
4099

4100
                // Report remote commit. May not be present when DLP is active.
4101
                if waitingClose.RemoteCommitment.CommitTx != nil {
6✔
4102
                        commitments.RemoteTxid =
3✔
4103
                                waitingClose.RemoteCommitment.CommitTx.TxHash().
3✔
4104
                                        String()
3✔
4105

3✔
4106
                        commitments.RemoteCommitFeeSat = uint64(
3✔
4107
                                waitingClose.RemoteCommitment.CommitFee,
3✔
4108
                        )
3✔
4109
                }
3✔
4110

4111
                // Report the remote pending commit if any.
4112
                remoteCommitDiff, err := waitingClose.RemoteCommitChainTip()
3✔
4113

3✔
4114
                switch {
3✔
4115
                // Don't set hash if there is no pending remote commit.
4116
                case err == channeldb.ErrNoPendingCommit:
3✔
4117

4118
                // An unexpected error occurred.
4119
                case err != nil:
×
4120
                        return nil, 0, err
×
4121

4122
                // There is a pending remote commit. Set its hash in the
4123
                // response.
4124
                default:
×
4125
                        hash := remoteCommitDiff.Commitment.CommitTx.TxHash()
×
4126
                        commitments.RemotePendingTxid = hash.String()
×
4127
                        commitments.RemoteCommitFeeSat = uint64(
×
4128
                                remoteCommitDiff.Commitment.CommitFee,
×
4129
                        )
×
4130
                }
4131

4132
                fwdPkgs, err := waitingClose.LoadFwdPkgs()
3✔
4133
                if err != nil {
3✔
4134
                        rpcsLog.Errorf("unable to load forwarding packages "+
×
4135
                                "for channel:%s, %v",
×
4136
                                waitingClose.ShortChannelID, err)
×
4137
                        return nil, 0, err
×
4138
                }
×
4139

4140
                // Get the closing tx.
4141
                // NOTE: the closing tx could be nil here if it's the remote
4142
                // that broadcasted the closing tx.
4143
                closingTx, err := getClosingTx(waitingClose)
3✔
4144
                if err != nil {
3✔
4145
                        rpcsLog.Errorf("unable to find closing tx for "+
×
4146
                                "channel:%s, %v",
×
4147
                                waitingClose.ShortChannelID, err)
×
4148
                        return nil, 0, err
×
4149
                }
×
4150

4151
                channel := &lnrpc.PendingChannelsResponse_PendingChannel{
3✔
4152
                        RemoteNodePub:         hex.EncodeToString(pub),
3✔
4153
                        ChannelPoint:          chanPoint.String(),
3✔
4154
                        Capacity:              int64(waitingClose.Capacity),
3✔
4155
                        LocalBalance:          int64(waitingClose.LocalCommitment.LocalBalance.ToSatoshis()),
3✔
4156
                        RemoteBalance:         int64(waitingClose.LocalCommitment.RemoteBalance.ToSatoshis()),
3✔
4157
                        LocalChanReserveSat:   int64(waitingClose.LocalChanCfg.ChanReserve),
3✔
4158
                        RemoteChanReserveSat:  int64(waitingClose.RemoteChanCfg.ChanReserve),
3✔
4159
                        Initiator:             rpcInitiator(waitingClose.IsInitiator),
3✔
4160
                        CommitmentType:        rpcCommitmentType(waitingClose.ChanType),
3✔
4161
                        NumForwardingPackages: int64(len(fwdPkgs)),
3✔
4162
                        ChanStatusFlags:       waitingClose.ChanStatus().String(),
3✔
4163
                        Private:               isPrivate(waitingClose),
3✔
4164
                        Memo:                  string(waitingClose.Memo),
3✔
4165
                }
3✔
4166

3✔
4167
                var closingTxid, closingTxHex string
3✔
4168
                if closingTx != nil {
6✔
4169
                        closingTxid = closingTx.TxHash().String()
3✔
4170
                        if includeRawTx {
6✔
4171
                                var txBuf bytes.Buffer
3✔
4172
                                err = closingTx.Serialize(&txBuf)
3✔
4173
                                if err != nil {
3✔
4174
                                        return nil, 0, fmt.Errorf("failed to "+
×
4175
                                                "serialize closing transaction"+
×
4176
                                                ": %w", err)
×
4177
                                }
×
4178
                                closingTxHex = hex.EncodeToString(txBuf.Bytes())
3✔
4179
                        }
4180
                }
4181

4182
                waitingCloseResp := &lnrpc.PendingChannelsResponse_WaitingCloseChannel{
3✔
4183
                        Channel:      channel,
3✔
4184
                        LimboBalance: channel.LocalBalance,
3✔
4185
                        Commitments:  &commitments,
3✔
4186
                        ClosingTxid:  closingTxid,
3✔
4187
                        ClosingTxHex: closingTxHex,
3✔
4188
                }
3✔
4189

3✔
4190
                // A close tx has been broadcasted, all our balance will be in
3✔
4191
                // limbo until it confirms.
3✔
4192
                result = append(result, waitingCloseResp)
3✔
4193
                limboBalance += channel.LocalBalance
3✔
4194
        }
4195

4196
        return result, limboBalance, nil
3✔
4197
}
4198

4199
// PendingChannels returns a list of all the channels that are currently
4200
// considered "pending". A channel is pending if it has finished the funding
4201
// workflow and is waiting for confirmations for the funding txn, or is in the
4202
// process of closure, either initiated cooperatively or non-cooperatively.
4203
func (r *rpcServer) PendingChannels(ctx context.Context,
4204
        in *lnrpc.PendingChannelsRequest) (
4205
        *lnrpc.PendingChannelsResponse, error) {
3✔
4206

3✔
4207
        resp := &lnrpc.PendingChannelsResponse{}
3✔
4208

3✔
4209
        // First, we find all the channels that will soon be opened.
3✔
4210
        pendingOpenChannels, err := r.fetchPendingOpenChannels()
3✔
4211
        if err != nil {
3✔
4212
                return nil, err
×
4213
        }
×
4214
        resp.PendingOpenChannels = pendingOpenChannels
3✔
4215

3✔
4216
        // Second, we fetch all channels that considered pending force closing.
3✔
4217
        // This means the channels here have their closing transactions
3✔
4218
        // confirmed but not considered fully resolved yet. For instance, they
3✔
4219
        // may have a second level HTLCs to be resolved onchain.
3✔
4220
        pendingCloseChannels, limbo, err := r.fetchPendingForceCloseChannels()
3✔
4221
        if err != nil {
3✔
4222
                return nil, err
×
4223
        }
×
4224
        resp.PendingForceClosingChannels = pendingCloseChannels
3✔
4225
        resp.TotalLimboBalance = limbo
3✔
4226

3✔
4227
        // Third, we fetch all channels that are open, but have had their
3✔
4228
        // commitment broadcasted, meaning they are waiting for the closing
3✔
4229
        // transaction to confirm.
3✔
4230
        waitingCloseChannels, limbo, err := r.fetchWaitingCloseChannels(
3✔
4231
                in.IncludeRawTx,
3✔
4232
        )
3✔
4233
        if err != nil {
3✔
4234
                return nil, err
×
4235
        }
×
4236
        resp.WaitingCloseChannels = waitingCloseChannels
3✔
4237
        resp.TotalLimboBalance += limbo
3✔
4238

3✔
4239
        err = fn.MapOptionZ(
3✔
4240
                r.server.implCfg.AuxDataParser,
3✔
4241
                func(parser AuxDataParser) error {
3✔
4242
                        return parser.InlineParseCustomData(resp)
×
4243
                },
×
4244
        )
4245
        if err != nil {
3✔
4246
                return nil, fmt.Errorf("error parsing custom data: %w", err)
×
4247
        }
×
4248

4249
        return resp, nil
3✔
4250
}
4251

4252
// arbitratorPopulateForceCloseResp populates the pending channels response
4253
// message with channel resolution information from the contract resolvers.
4254
func (r *rpcServer) arbitratorPopulateForceCloseResp(chanPoint *wire.OutPoint,
4255
        currentHeight int32,
4256
        forceClose *lnrpc.PendingChannelsResponse_ForceClosedChannel) error {
3✔
4257

3✔
4258
        // Query for contract resolvers state.
3✔
4259
        arbitrator, err := r.server.chainArb.GetChannelArbitrator(*chanPoint)
3✔
4260
        if err != nil {
3✔
4261
                return err
×
4262
        }
×
4263
        reports := arbitrator.Report()
3✔
4264

3✔
4265
        for _, report := range reports {
6✔
4266
                switch report.Type {
3✔
4267
                // For a direct output, populate/update the top level
4268
                // response properties.
4269
                case contractcourt.ReportOutputUnencumbered:
3✔
4270
                        // Populate the maturity height fields for the direct
3✔
4271
                        // commitment output to us.
3✔
4272
                        forceClose.MaturityHeight = report.MaturityHeight
3✔
4273

3✔
4274
                        // If the transaction has been confirmed, then we can
3✔
4275
                        // compute how many blocks it has left.
3✔
4276
                        if forceClose.MaturityHeight != 0 {
6✔
4277
                                forceClose.BlocksTilMaturity =
3✔
4278
                                        int32(forceClose.MaturityHeight) -
3✔
4279
                                                currentHeight
3✔
4280
                        }
3✔
4281

4282
                // Add htlcs to the PendingHtlcs response property.
4283
                case contractcourt.ReportOutputIncomingHtlc,
4284
                        contractcourt.ReportOutputOutgoingHtlc:
3✔
4285

3✔
4286
                        // Don't report details on htlcs that are no longer in
3✔
4287
                        // limbo.
3✔
4288
                        if report.LimboBalance == 0 {
6✔
4289
                                break
3✔
4290
                        }
4291

4292
                        incoming := report.Type == contractcourt.ReportOutputIncomingHtlc
3✔
4293
                        htlc := &lnrpc.PendingHTLC{
3✔
4294
                                Incoming:       incoming,
3✔
4295
                                Amount:         int64(report.Amount),
3✔
4296
                                Outpoint:       report.Outpoint.String(),
3✔
4297
                                MaturityHeight: report.MaturityHeight,
3✔
4298
                                Stage:          report.Stage,
3✔
4299
                        }
3✔
4300

3✔
4301
                        if htlc.MaturityHeight != 0 {
6✔
4302
                                htlc.BlocksTilMaturity =
3✔
4303
                                        int32(htlc.MaturityHeight) - currentHeight
3✔
4304
                        }
3✔
4305

4306
                        forceClose.PendingHtlcs = append(forceClose.PendingHtlcs, htlc)
3✔
4307

4308
                case contractcourt.ReportOutputAnchor:
3✔
4309
                        // There are three resolution states for the anchor:
3✔
4310
                        // limbo, lost and recovered. Derive the current state
3✔
4311
                        // from the limbo and recovered balances.
3✔
4312
                        switch {
3✔
4313
                        case report.RecoveredBalance != 0:
3✔
4314
                                forceClose.Anchor = lnrpc.PendingChannelsResponse_ForceClosedChannel_RECOVERED
3✔
4315

4316
                        case report.LimboBalance != 0:
3✔
4317
                                forceClose.Anchor = lnrpc.PendingChannelsResponse_ForceClosedChannel_LIMBO
3✔
4318

4319
                        default:
3✔
4320
                                forceClose.Anchor = lnrpc.PendingChannelsResponse_ForceClosedChannel_LOST
3✔
4321
                        }
4322

4323
                default:
×
4324
                        return fmt.Errorf("unknown report output type: %v",
×
4325
                                report.Type)
×
4326
                }
4327

4328
                forceClose.LimboBalance += int64(report.LimboBalance)
3✔
4329
                forceClose.RecoveredBalance += int64(report.RecoveredBalance)
3✔
4330
        }
4331

4332
        return nil
3✔
4333
}
4334

4335
// nurseryPopulateForceCloseResp populates the pending channels response
4336
// message with contract resolution information from utxonursery.
4337
func (r *rpcServer) nurseryPopulateForceCloseResp(chanPoint *wire.OutPoint,
4338
        currentHeight int32,
4339
        forceClose *lnrpc.PendingChannelsResponse_ForceClosedChannel) error {
3✔
4340

3✔
4341
        // Query for the maturity state for this force closed channel. If we
3✔
4342
        // didn't have any time-locked outputs, then the nursery may not know of
3✔
4343
        // the contract.
3✔
4344
        nurseryInfo, err := r.server.utxoNursery.NurseryReport(chanPoint)
3✔
4345
        if err == contractcourt.ErrContractNotFound {
6✔
4346
                return nil
3✔
4347
        }
3✔
4348
        if err != nil {
3✔
4349
                return fmt.Errorf("unable to obtain "+
×
4350
                        "nursery report for ChannelPoint(%v): %v",
×
4351
                        chanPoint, err)
×
4352
        }
×
4353

4354
        // If the nursery knows of this channel, then we can populate
4355
        // information detailing exactly how much funds are time locked and also
4356
        // the height in which we can ultimately sweep the funds into the
4357
        // wallet.
4358
        forceClose.LimboBalance = int64(nurseryInfo.LimboBalance)
3✔
4359
        forceClose.RecoveredBalance = int64(nurseryInfo.RecoveredBalance)
3✔
4360

3✔
4361
        for _, htlcReport := range nurseryInfo.Htlcs {
6✔
4362
                // TODO(conner) set incoming flag appropriately after handling
3✔
4363
                // incoming incubation
3✔
4364
                htlc := &lnrpc.PendingHTLC{
3✔
4365
                        Incoming:       false,
3✔
4366
                        Amount:         int64(htlcReport.Amount),
3✔
4367
                        Outpoint:       htlcReport.Outpoint.String(),
3✔
4368
                        MaturityHeight: htlcReport.MaturityHeight,
3✔
4369
                        Stage:          htlcReport.Stage,
3✔
4370
                }
3✔
4371

3✔
4372
                if htlc.MaturityHeight != 0 {
6✔
4373
                        htlc.BlocksTilMaturity =
3✔
4374
                                int32(htlc.MaturityHeight) -
3✔
4375
                                        currentHeight
3✔
4376
                }
3✔
4377

4378
                forceClose.PendingHtlcs = append(forceClose.PendingHtlcs,
3✔
4379
                        htlc)
3✔
4380
        }
4381

4382
        return nil
3✔
4383
}
4384

4385
// ClosedChannels returns a list of all the channels have been closed.
4386
// This does not include channels that are still in the process of closing.
4387
func (r *rpcServer) ClosedChannels(ctx context.Context,
4388
        in *lnrpc.ClosedChannelsRequest) (*lnrpc.ClosedChannelsResponse,
4389
        error) {
3✔
4390

3✔
4391
        // Show all channels when no filter flags are set.
3✔
4392
        filterResults := in.Cooperative || in.LocalForce ||
3✔
4393
                in.RemoteForce || in.Breach || in.FundingCanceled ||
3✔
4394
                in.Abandoned
3✔
4395

3✔
4396
        resp := &lnrpc.ClosedChannelsResponse{}
3✔
4397

3✔
4398
        dbChannels, err := r.server.chanStateDB.FetchClosedChannels(false)
3✔
4399
        if err != nil {
3✔
4400
                return nil, err
×
4401
        }
×
4402

4403
        // In order to make the response easier to parse for clients, we'll
4404
        // sort the set of closed channels by their closing height before
4405
        // serializing the proto response.
4406
        sort.Slice(dbChannels, func(i, j int) bool {
6✔
4407
                return dbChannels[i].CloseHeight < dbChannels[j].CloseHeight
3✔
4408
        })
3✔
4409

4410
        for _, dbChannel := range dbChannels {
6✔
4411
                if dbChannel.IsPending {
3✔
4412
                        continue
×
4413
                }
4414

4415
                switch dbChannel.CloseType {
3✔
4416
                case channeldb.CooperativeClose:
3✔
4417
                        if filterResults && !in.Cooperative {
3✔
4418
                                continue
×
4419
                        }
4420
                case channeldb.LocalForceClose:
3✔
4421
                        if filterResults && !in.LocalForce {
3✔
4422
                                continue
×
4423
                        }
4424
                case channeldb.RemoteForceClose:
3✔
4425
                        if filterResults && !in.RemoteForce {
3✔
4426
                                continue
×
4427
                        }
4428
                case channeldb.BreachClose:
×
4429
                        if filterResults && !in.Breach {
×
4430
                                continue
×
4431
                        }
4432
                case channeldb.FundingCanceled:
×
4433
                        if filterResults && !in.FundingCanceled {
×
4434
                                continue
×
4435
                        }
4436
                case channeldb.Abandoned:
3✔
4437
                        if filterResults && !in.Abandoned {
3✔
4438
                                continue
×
4439
                        }
4440
                }
4441

4442
                channel, err := r.createRPCClosedChannel(dbChannel)
3✔
4443
                if err != nil {
3✔
4444
                        return nil, err
×
4445
                }
×
4446

4447
                resp.Channels = append(resp.Channels, channel)
3✔
4448
        }
4449

4450
        return resp, nil
3✔
4451
}
4452

4453
// LookupHtlcResolution retrieves a final htlc resolution from the database. If
4454
// the htlc has no final resolution yet, a NotFound grpc status code is
4455
// returned.
4456
func (r *rpcServer) LookupHtlcResolution(
4457
        _ context.Context, in *lnrpc.LookupHtlcResolutionRequest) (
4458
        *lnrpc.LookupHtlcResolutionResponse, error) {
3✔
4459

3✔
4460
        if !r.cfg.StoreFinalHtlcResolutions {
6✔
4461
                return nil, status.Error(codes.Unavailable, "cannot lookup "+
3✔
4462
                        "with flag --store-final-htlc-resolutions=false")
3✔
4463
        }
3✔
4464

4465
        chanID := lnwire.NewShortChanIDFromInt(in.ChanId)
3✔
4466

3✔
4467
        info, err := r.server.chanStateDB.LookupFinalHtlc(chanID, in.HtlcIndex)
3✔
4468
        switch {
3✔
4469
        case errors.Is(err, channeldb.ErrHtlcUnknown):
×
4470
                return nil, status.Error(codes.NotFound, err.Error())
×
4471

4472
        case err != nil:
×
4473
                return nil, err
×
4474
        }
4475

4476
        return &lnrpc.LookupHtlcResolutionResponse{
3✔
4477
                Settled:  info.Settled,
3✔
4478
                Offchain: info.Offchain,
3✔
4479
        }, nil
3✔
4480
}
4481

4482
// ListChannels returns a description of all the open channels that this node
4483
// is a participant in.
4484
func (r *rpcServer) ListChannels(ctx context.Context,
4485
        in *lnrpc.ListChannelsRequest) (*lnrpc.ListChannelsResponse, error) {
3✔
4486

3✔
4487
        if in.ActiveOnly && in.InactiveOnly {
6✔
4488
                return nil, fmt.Errorf("either `active_only` or " +
3✔
4489
                        "`inactive_only` can be set, but not both")
3✔
4490
        }
3✔
4491

4492
        if in.PublicOnly && in.PrivateOnly {
3✔
4493
                return nil, fmt.Errorf("either `public_only` or " +
×
4494
                        "`private_only` can be set, but not both")
×
4495
        }
×
4496

4497
        if len(in.Peer) > 0 && len(in.Peer) != 33 {
3✔
4498
                _, err := route.NewVertexFromBytes(in.Peer)
×
4499
                return nil, fmt.Errorf("invalid `peer` key: %w", err)
×
4500
        }
×
4501

4502
        resp := &lnrpc.ListChannelsResponse{}
3✔
4503

3✔
4504
        dbChannels, err := r.server.chanStateDB.FetchAllOpenChannels()
3✔
4505
        if err != nil {
3✔
4506
                return nil, err
×
4507
        }
×
4508

4509
        rpcsLog.Debugf("[listchannels] fetched %v channels from DB",
3✔
4510
                len(dbChannels))
3✔
4511

3✔
4512
        for _, dbChannel := range dbChannels {
6✔
4513
                nodePub := dbChannel.IdentityPub
3✔
4514
                nodePubBytes := nodePub.SerializeCompressed()
3✔
4515
                chanPoint := dbChannel.FundingOutpoint
3✔
4516

3✔
4517
                // If the caller requested channels for a target node, skip any
3✔
4518
                // that don't match the provided pubkey.
3✔
4519
                if len(in.Peer) > 0 && !bytes.Equal(nodePubBytes, in.Peer) {
6✔
4520
                        continue
3✔
4521
                }
4522

4523
                var peerOnline bool
3✔
4524
                if _, err := r.server.FindPeer(nodePub); err == nil {
6✔
4525
                        peerOnline = true
3✔
4526
                }
3✔
4527

4528
                channelID := lnwire.NewChanIDFromOutPoint(chanPoint)
3✔
4529
                var linkActive bool
3✔
4530
                if link, err := r.server.htlcSwitch.GetLink(channelID); err == nil {
6✔
4531
                        // A channel is only considered active if it is known
3✔
4532
                        // by the switch *and* able to forward
3✔
4533
                        // incoming/outgoing payments.
3✔
4534
                        linkActive = link.EligibleToForward()
3✔
4535
                }
3✔
4536

4537
                // Next, we'll determine whether we should add this channel to
4538
                // our list depending on the type of channels requested to us.
4539
                isActive := peerOnline && linkActive
3✔
4540
                channel, err := createRPCOpenChannel(
3✔
4541
                        r, dbChannel, isActive, in.PeerAliasLookup,
3✔
4542
                )
3✔
4543
                if err != nil {
3✔
4544
                        return nil, err
×
4545
                }
×
4546

4547
                // We'll only skip returning this channel if we were requested
4548
                // for a specific kind and this channel doesn't satisfy it.
4549
                switch {
3✔
4550
                case in.ActiveOnly && !isActive:
3✔
4551
                        continue
3✔
4552
                case in.InactiveOnly && isActive:
×
4553
                        continue
×
4554
                case in.PublicOnly && channel.Private:
×
4555
                        continue
×
4556
                case in.PrivateOnly && !channel.Private:
3✔
4557
                        continue
3✔
4558
                }
4559

4560
                resp.Channels = append(resp.Channels, channel)
3✔
4561
        }
4562

4563
        err = fn.MapOptionZ(
3✔
4564
                r.server.implCfg.AuxDataParser,
3✔
4565
                func(parser AuxDataParser) error {
3✔
4566
                        return parser.InlineParseCustomData(resp)
×
4567
                },
×
4568
        )
4569
        if err != nil {
3✔
4570
                return nil, fmt.Errorf("error parsing custom data: %w", err)
×
4571
        }
×
4572

4573
        return resp, nil
3✔
4574
}
4575

4576
// rpcCommitmentType takes the channel type and converts it to an rpc commitment
4577
// type value.
4578
func rpcCommitmentType(chanType channeldb.ChannelType) lnrpc.CommitmentType {
3✔
4579
        // Extract the commitment type from the channel type flags. We must
3✔
4580
        // first check whether it has anchors, since in that case it would also
3✔
4581
        // be tweakless.
3✔
4582
        switch {
3✔
4583
        case chanType.HasTapscriptRoot():
×
4584
                return lnrpc.CommitmentType_SIMPLE_TAPROOT_OVERLAY
×
4585

4586
        case chanType.IsTaproot():
3✔
4587
                return lnrpc.CommitmentType_SIMPLE_TAPROOT
3✔
4588

4589
        case chanType.HasLeaseExpiration():
3✔
4590
                return lnrpc.CommitmentType_SCRIPT_ENFORCED_LEASE
3✔
4591

4592
        case chanType.HasAnchors():
3✔
4593
                return lnrpc.CommitmentType_ANCHORS
3✔
4594

4595
        case chanType.IsTweakless():
3✔
4596
                return lnrpc.CommitmentType_STATIC_REMOTE_KEY
3✔
4597

4598
        default:
3✔
4599

3✔
4600
                return lnrpc.CommitmentType_LEGACY
3✔
4601
        }
4602
}
4603

4604
// createChannelConstraint creates a *lnrpc.ChannelConstraints using the
4605
// *Channeldb.ChannelConfig.
4606
func createChannelConstraint(
4607
        chanCfg *channeldb.ChannelConfig) *lnrpc.ChannelConstraints {
3✔
4608
        return &lnrpc.ChannelConstraints{
3✔
4609
                CsvDelay:          uint32(chanCfg.CsvDelay),
3✔
4610
                ChanReserveSat:    uint64(chanCfg.ChanReserve),
3✔
4611
                DustLimitSat:      uint64(chanCfg.DustLimit),
3✔
4612
                MaxPendingAmtMsat: uint64(chanCfg.MaxPendingAmount),
3✔
4613
                MinHtlcMsat:       uint64(chanCfg.MinHTLC),
3✔
4614
                MaxAcceptedHtlcs:  uint32(chanCfg.MaxAcceptedHtlcs),
3✔
4615
        }
3✔
4616
}
3✔
4617

4618
// isPrivate evaluates the ChannelFlags of the db channel to determine if the
4619
// channel is private or not.
4620
func isPrivate(dbChannel *channeldb.OpenChannel) bool {
3✔
4621
        if dbChannel == nil {
3✔
4622
                return false
×
4623
        }
×
4624
        return dbChannel.ChannelFlags&lnwire.FFAnnounceChannel != 1
3✔
4625
}
4626

4627
// encodeCustomChanData encodes the custom channel data for the open channel.
4628
// It encodes that data as a pair of var bytes blobs.
4629
func encodeCustomChanData(lnChan *channeldb.OpenChannel) ([]byte, error) {
3✔
4630
        customOpenChanData := lnChan.CustomBlob.UnwrapOr(nil)
3✔
4631
        customLocalCommitData := lnChan.LocalCommitment.CustomBlob.UnwrapOr(nil)
3✔
4632

3✔
4633
        // Don't write any custom data if both blobs are empty.
3✔
4634
        if len(customOpenChanData) == 0 && len(customLocalCommitData) == 0 {
6✔
4635
                return nil, nil
3✔
4636
        }
3✔
4637

4638
        // We'll encode our custom channel data as two blobs. The first is a
4639
        // set of var bytes encoding of the open chan data, the second is an
4640
        // encoding of the local commitment data.
4641
        var customChanDataBuf bytes.Buffer
×
4642
        err := wire.WriteVarBytes(&customChanDataBuf, 0, customOpenChanData)
×
4643
        if err != nil {
×
4644
                return nil, fmt.Errorf("unable to encode open chan "+
×
4645
                        "data: %w", err)
×
4646
        }
×
4647
        err = wire.WriteVarBytes(&customChanDataBuf, 0, customLocalCommitData)
×
4648
        if err != nil {
×
4649
                return nil, fmt.Errorf("unable to encode local commit "+
×
4650
                        "data: %w", err)
×
4651
        }
×
4652

4653
        return customChanDataBuf.Bytes(), nil
×
4654
}
4655

4656
// createRPCOpenChannel creates an *lnrpc.Channel from the *channeldb.Channel.
4657
func createRPCOpenChannel(r *rpcServer, dbChannel *channeldb.OpenChannel,
4658
        isActive, peerAliasLookup bool) (*lnrpc.Channel, error) {
3✔
4659

3✔
4660
        nodePub := dbChannel.IdentityPub
3✔
4661
        nodeID := hex.EncodeToString(nodePub.SerializeCompressed())
3✔
4662
        chanPoint := dbChannel.FundingOutpoint
3✔
4663
        chanID := lnwire.NewChanIDFromOutPoint(chanPoint)
3✔
4664

3✔
4665
        // As this is required for display purposes, we'll calculate
3✔
4666
        // the weight of the commitment transaction. We also add on the
3✔
4667
        // estimated weight of the witness to calculate the weight of
3✔
4668
        // the transaction if it were to be immediately unilaterally
3✔
4669
        // broadcast.
3✔
4670
        var witnessWeight int64
3✔
4671
        if dbChannel.ChanType.IsTaproot() {
6✔
4672
                witnessWeight = input.TaprootKeyPathWitnessSize
3✔
4673
        } else {
6✔
4674
                witnessWeight = input.WitnessCommitmentTxWeight
3✔
4675
        }
3✔
4676

4677
        localCommit := dbChannel.LocalCommitment
3✔
4678
        utx := btcutil.NewTx(localCommit.CommitTx)
3✔
4679
        commitBaseWeight := blockchain.GetTransactionWeight(utx)
3✔
4680
        commitWeight := commitBaseWeight + witnessWeight
3✔
4681

3✔
4682
        localBalance := localCommit.LocalBalance
3✔
4683
        remoteBalance := localCommit.RemoteBalance
3✔
4684

3✔
4685
        // As an artifact of our usage of mSAT internally, either party
3✔
4686
        // may end up in a state where they're holding a fractional
3✔
4687
        // amount of satoshis which can't be expressed within the
3✔
4688
        // actual commitment output. Since we round down when going
3✔
4689
        // from mSAT -> SAT, we may at any point be adding an
3✔
4690
        // additional SAT to miners fees. As a result, we display a
3✔
4691
        // commitment fee that accounts for this externally.
3✔
4692
        var sumOutputs btcutil.Amount
3✔
4693
        for _, txOut := range localCommit.CommitTx.TxOut {
6✔
4694
                sumOutputs += btcutil.Amount(txOut.Value)
3✔
4695
        }
3✔
4696
        externalCommitFee := dbChannel.Capacity - sumOutputs
3✔
4697

3✔
4698
        // Extract the commitment type from the channel type flags.
3✔
4699
        commitmentType := rpcCommitmentType(dbChannel.ChanType)
3✔
4700

3✔
4701
        dbScid := dbChannel.ShortChannelID
3✔
4702

3✔
4703
        // Fetch the set of aliases for the channel.
3✔
4704
        channelAliases := r.server.aliasMgr.GetAliases(dbScid)
3✔
4705

3✔
4706
        // Fetch the peer alias. If one does not exist, errNoPeerAlias
3✔
4707
        // is returned and peerScidAlias will be an empty ShortChannelID.
3✔
4708
        peerScidAlias, _ := r.server.aliasMgr.GetPeerAlias(chanID)
3✔
4709

3✔
4710
        // Finally we'll attempt to encode the custom channel data if any
3✔
4711
        // exists.
3✔
4712
        customChanBytes, err := encodeCustomChanData(dbChannel)
3✔
4713
        if err != nil {
3✔
4714
                return nil, fmt.Errorf("unable to encode open chan data: %w",
×
4715
                        err)
×
4716
        }
×
4717

4718
        channel := &lnrpc.Channel{
3✔
4719
                Active:                isActive,
3✔
4720
                Private:               isPrivate(dbChannel),
3✔
4721
                RemotePubkey:          nodeID,
3✔
4722
                ChannelPoint:          chanPoint.String(),
3✔
4723
                ChanId:                dbScid.ToUint64(),
3✔
4724
                Capacity:              int64(dbChannel.Capacity),
3✔
4725
                LocalBalance:          int64(localBalance.ToSatoshis()),
3✔
4726
                RemoteBalance:         int64(remoteBalance.ToSatoshis()),
3✔
4727
                CommitFee:             int64(externalCommitFee),
3✔
4728
                CommitWeight:          commitWeight,
3✔
4729
                FeePerKw:              int64(localCommit.FeePerKw),
3✔
4730
                TotalSatoshisSent:     int64(dbChannel.TotalMSatSent.ToSatoshis()),
3✔
4731
                TotalSatoshisReceived: int64(dbChannel.TotalMSatReceived.ToSatoshis()),
3✔
4732
                NumUpdates:            localCommit.CommitHeight,
3✔
4733
                PendingHtlcs:          make([]*lnrpc.HTLC, len(localCommit.Htlcs)),
3✔
4734
                Initiator:             dbChannel.IsInitiator,
3✔
4735
                ChanStatusFlags:       dbChannel.ChanStatus().String(),
3✔
4736
                StaticRemoteKey:       commitmentType == lnrpc.CommitmentType_STATIC_REMOTE_KEY,
3✔
4737
                CommitmentType:        commitmentType,
3✔
4738
                ThawHeight:            dbChannel.ThawHeight,
3✔
4739
                LocalConstraints: createChannelConstraint(
3✔
4740
                        &dbChannel.LocalChanCfg,
3✔
4741
                ),
3✔
4742
                RemoteConstraints: createChannelConstraint(
3✔
4743
                        &dbChannel.RemoteChanCfg,
3✔
4744
                ),
3✔
4745
                AliasScids:            make([]uint64, 0, len(channelAliases)),
3✔
4746
                PeerScidAlias:         peerScidAlias.ToUint64(),
3✔
4747
                ZeroConf:              dbChannel.IsZeroConf(),
3✔
4748
                ZeroConfConfirmedScid: dbChannel.ZeroConfRealScid().ToUint64(),
3✔
4749
                Memo:                  string(dbChannel.Memo),
3✔
4750
                CustomChannelData:     customChanBytes,
3✔
4751
                // TODO: remove the following deprecated fields
3✔
4752
                CsvDelay:             uint32(dbChannel.LocalChanCfg.CsvDelay),
3✔
4753
                LocalChanReserveSat:  int64(dbChannel.LocalChanCfg.ChanReserve),
3✔
4754
                RemoteChanReserveSat: int64(dbChannel.RemoteChanCfg.ChanReserve),
3✔
4755
        }
3✔
4756

3✔
4757
        // Look up our channel peer's node alias if the caller requests it.
3✔
4758
        if peerAliasLookup {
6✔
4759
                peerAlias, err := r.server.graphDB.LookupAlias(nodePub)
3✔
4760
                if err != nil {
3✔
4761
                        peerAlias = fmt.Sprintf("unable to lookup "+
×
4762
                                "peer alias: %v", err)
×
4763
                }
×
4764
                channel.PeerAlias = peerAlias
3✔
4765
        }
4766

4767
        // Populate the set of aliases.
4768
        for _, chanAlias := range channelAliases {
6✔
4769
                channel.AliasScids = append(
3✔
4770
                        channel.AliasScids, chanAlias.ToUint64(),
3✔
4771
                )
3✔
4772
        }
3✔
4773

4774
        for i, htlc := range localCommit.Htlcs {
6✔
4775
                var rHash [32]byte
3✔
4776
                copy(rHash[:], htlc.RHash[:])
3✔
4777

3✔
4778
                circuitMap := r.server.htlcSwitch.CircuitLookup()
3✔
4779

3✔
4780
                var forwardingChannel, forwardingHtlcIndex uint64
3✔
4781
                switch {
3✔
4782
                case htlc.Incoming:
3✔
4783
                        circuit := circuitMap.LookupCircuit(
3✔
4784
                                htlcswitch.CircuitKey{
3✔
4785
                                        ChanID: dbChannel.ShortChannelID,
3✔
4786
                                        HtlcID: htlc.HtlcIndex,
3✔
4787
                                },
3✔
4788
                        )
3✔
4789
                        if circuit != nil && circuit.Outgoing != nil {
6✔
4790
                                forwardingChannel = circuit.Outgoing.ChanID.
3✔
4791
                                        ToUint64()
3✔
4792

3✔
4793
                                forwardingHtlcIndex = circuit.Outgoing.HtlcID
3✔
4794
                        }
3✔
4795

4796
                case !htlc.Incoming:
3✔
4797
                        circuit := circuitMap.LookupOpenCircuit(
3✔
4798
                                htlcswitch.CircuitKey{
3✔
4799
                                        ChanID: dbChannel.ShortChannelID,
3✔
4800
                                        HtlcID: htlc.HtlcIndex,
3✔
4801
                                },
3✔
4802
                        )
3✔
4803

3✔
4804
                        // If the incoming channel id is the special hop.Source
3✔
4805
                        // value, the htlc index is a local payment identifier.
3✔
4806
                        // In this case, report nothing.
3✔
4807
                        if circuit != nil &&
3✔
4808
                                circuit.Incoming.ChanID != hop.Source {
6✔
4809

3✔
4810
                                forwardingChannel = circuit.Incoming.ChanID.
3✔
4811
                                        ToUint64()
3✔
4812

3✔
4813
                                forwardingHtlcIndex = circuit.Incoming.HtlcID
3✔
4814
                        }
3✔
4815
                }
4816

4817
                channel.PendingHtlcs[i] = &lnrpc.HTLC{
3✔
4818
                        Incoming:            htlc.Incoming,
3✔
4819
                        Amount:              int64(htlc.Amt.ToSatoshis()),
3✔
4820
                        HashLock:            rHash[:],
3✔
4821
                        ExpirationHeight:    htlc.RefundTimeout,
3✔
4822
                        HtlcIndex:           htlc.HtlcIndex,
3✔
4823
                        ForwardingChannel:   forwardingChannel,
3✔
4824
                        ForwardingHtlcIndex: forwardingHtlcIndex,
3✔
4825
                }
3✔
4826

3✔
4827
                // Add the Pending Htlc Amount to UnsettledBalance field.
3✔
4828
                channel.UnsettledBalance += channel.PendingHtlcs[i].Amount
3✔
4829
        }
4830

4831
        // If we initiated opening the channel, the zero height remote balance
4832
        // is the push amount. Otherwise, our starting balance is the push
4833
        // amount. If there is no push amount, these values will simply be zero.
4834
        if dbChannel.IsInitiator {
6✔
4835
                amt := dbChannel.InitialRemoteBalance.ToSatoshis()
3✔
4836
                channel.PushAmountSat = uint64(amt)
3✔
4837
        } else {
6✔
4838
                amt := dbChannel.InitialLocalBalance.ToSatoshis()
3✔
4839
                channel.PushAmountSat = uint64(amt)
3✔
4840
        }
3✔
4841

4842
        if len(dbChannel.LocalShutdownScript) > 0 {
6✔
4843
                _, addresses, _, err := txscript.ExtractPkScriptAddrs(
3✔
4844
                        dbChannel.LocalShutdownScript, r.cfg.ActiveNetParams.Params,
3✔
4845
                )
3✔
4846
                if err != nil {
3✔
4847
                        return nil, err
×
4848
                }
×
4849

4850
                // We only expect one upfront shutdown address for a channel. If
4851
                // LocalShutdownScript is non-zero, there should be one payout
4852
                // address set.
4853
                if len(addresses) != 1 {
3✔
4854
                        return nil, fmt.Errorf("expected one upfront shutdown "+
×
4855
                                "address, got: %v", len(addresses))
×
4856
                }
×
4857

4858
                channel.CloseAddress = addresses[0].String()
3✔
4859
        }
4860

4861
        // If the server hasn't fully started yet, it's possible that the
4862
        // channel event store hasn't either, so it won't be able to consume any
4863
        // requests until then. To prevent blocking, we'll just omit the uptime
4864
        // related fields for now.
4865
        if !r.server.Started() {
3✔
4866
                return channel, nil
×
4867
        }
×
4868

4869
        peer, err := route.NewVertexFromBytes(nodePub.SerializeCompressed())
3✔
4870
        if err != nil {
3✔
4871
                return nil, err
×
4872
        }
×
4873

4874
        // Query the event store for additional information about the channel.
4875
        // Do not fail if it is not available, because there is a potential
4876
        // race between a channel being added to our node and the event store
4877
        // being notified of it.
4878
        outpoint := dbChannel.FundingOutpoint
3✔
4879
        info, err := r.server.chanEventStore.GetChanInfo(outpoint, peer)
3✔
4880
        switch err {
3✔
4881
        // If the store does not know about the channel, we just log it.
4882
        case chanfitness.ErrChannelNotFound:
3✔
4883
                rpcsLog.Infof("channel: %v not found by channel event store",
3✔
4884
                        outpoint)
3✔
4885

4886
        // If we got our channel info, we further populate the channel.
4887
        case nil:
3✔
4888
                channel.Uptime = int64(info.Uptime.Seconds())
3✔
4889
                channel.Lifetime = int64(info.Lifetime.Seconds())
3✔
4890

4891
        // If we get an unexpected error, we return it.
4892
        default:
×
4893
                return nil, err
×
4894
        }
4895

4896
        return channel, nil
3✔
4897
}
4898

4899
// createRPCClosedChannel creates an *lnrpc.ClosedChannelSummary from a
4900
// *channeldb.ChannelCloseSummary.
4901
func (r *rpcServer) createRPCClosedChannel(
4902
        dbChannel *channeldb.ChannelCloseSummary) (*lnrpc.ChannelCloseSummary, error) {
3✔
4903

3✔
4904
        nodePub := dbChannel.RemotePub
3✔
4905
        nodeID := hex.EncodeToString(nodePub.SerializeCompressed())
3✔
4906

3✔
4907
        var (
3✔
4908
                closeType      lnrpc.ChannelCloseSummary_ClosureType
3✔
4909
                openInit       lnrpc.Initiator
3✔
4910
                closeInitiator lnrpc.Initiator
3✔
4911
                err            error
3✔
4912
        )
3✔
4913

3✔
4914
        // Lookup local and remote cooperative initiators. If these values
3✔
4915
        // are not known they will just return unknown.
3✔
4916
        openInit, closeInitiator, err = r.getInitiators(
3✔
4917
                &dbChannel.ChanPoint,
3✔
4918
        )
3✔
4919
        if err != nil {
3✔
4920
                return nil, err
×
4921
        }
×
4922

4923
        // Convert the close type to rpc type.
4924
        switch dbChannel.CloseType {
3✔
4925
        case channeldb.CooperativeClose:
3✔
4926
                closeType = lnrpc.ChannelCloseSummary_COOPERATIVE_CLOSE
3✔
4927
        case channeldb.LocalForceClose:
3✔
4928
                closeType = lnrpc.ChannelCloseSummary_LOCAL_FORCE_CLOSE
3✔
4929
        case channeldb.RemoteForceClose:
3✔
4930
                closeType = lnrpc.ChannelCloseSummary_REMOTE_FORCE_CLOSE
3✔
4931
        case channeldb.BreachClose:
×
4932
                closeType = lnrpc.ChannelCloseSummary_BREACH_CLOSE
×
4933
        case channeldb.FundingCanceled:
×
4934
                closeType = lnrpc.ChannelCloseSummary_FUNDING_CANCELED
×
4935
        case channeldb.Abandoned:
3✔
4936
                closeType = lnrpc.ChannelCloseSummary_ABANDONED
3✔
4937
        }
4938

4939
        dbScid := dbChannel.ShortChanID
3✔
4940

3✔
4941
        // Fetch the set of aliases for this channel.
3✔
4942
        channelAliases := r.server.aliasMgr.GetAliases(dbScid)
3✔
4943

3✔
4944
        channel := &lnrpc.ChannelCloseSummary{
3✔
4945
                Capacity:          int64(dbChannel.Capacity),
3✔
4946
                RemotePubkey:      nodeID,
3✔
4947
                CloseHeight:       dbChannel.CloseHeight,
3✔
4948
                CloseType:         closeType,
3✔
4949
                ChannelPoint:      dbChannel.ChanPoint.String(),
3✔
4950
                ChanId:            dbChannel.ShortChanID.ToUint64(),
3✔
4951
                SettledBalance:    int64(dbChannel.SettledBalance),
3✔
4952
                TimeLockedBalance: int64(dbChannel.TimeLockedBalance),
3✔
4953
                ChainHash:         dbChannel.ChainHash.String(),
3✔
4954
                ClosingTxHash:     dbChannel.ClosingTXID.String(),
3✔
4955
                OpenInitiator:     openInit,
3✔
4956
                CloseInitiator:    closeInitiator,
3✔
4957
                AliasScids:        make([]uint64, 0, len(channelAliases)),
3✔
4958
        }
3✔
4959

3✔
4960
        // Populate the set of aliases.
3✔
4961
        for _, chanAlias := range channelAliases {
6✔
4962
                channel.AliasScids = append(
3✔
4963
                        channel.AliasScids, chanAlias.ToUint64(),
3✔
4964
                )
3✔
4965
        }
3✔
4966

4967
        // Populate any historical data that the summary needs.
4968
        histChan, err := r.server.chanStateDB.FetchHistoricalChannel(
3✔
4969
                &dbChannel.ChanPoint,
3✔
4970
        )
3✔
4971
        switch err {
3✔
4972
        // The channel was closed in a pre-historic version of lnd. Ignore the
4973
        // error.
4974
        case channeldb.ErrNoHistoricalBucket:
×
4975
        case channeldb.ErrChannelNotFound:
×
4976

4977
        case nil:
3✔
4978
                if histChan.IsZeroConf() && histChan.ZeroConfConfirmed() {
6✔
4979
                        // If the channel was zero-conf, it may have confirmed.
3✔
4980
                        // Populate the confirmed SCID if so.
3✔
4981
                        confirmedScid := histChan.ZeroConfRealScid().ToUint64()
3✔
4982
                        channel.ZeroConfConfirmedScid = confirmedScid
3✔
4983
                }
3✔
4984

4985
        // Non-nil error not due to older versions of lnd.
4986
        default:
×
4987
                return nil, err
×
4988
        }
4989

4990
        reports, err := r.server.miscDB.FetchChannelReports(
3✔
4991
                *r.cfg.ActiveNetParams.GenesisHash, &dbChannel.ChanPoint,
3✔
4992
        )
3✔
4993
        switch err {
3✔
4994
        // If the channel does not have its resolver outcomes stored,
4995
        // ignore it.
4996
        case channeldb.ErrNoChainHashBucket:
3✔
4997
                fallthrough
3✔
4998
        case channeldb.ErrNoChannelSummaries:
3✔
4999
                return channel, nil
3✔
5000

5001
        // If there is no error, fallthrough the switch to process reports.
5002
        case nil:
3✔
5003

5004
        // If another error occurred, return it.
5005
        default:
×
5006
                return nil, err
×
5007
        }
5008

5009
        for _, report := range reports {
6✔
5010
                rpcResolution, err := rpcChannelResolution(report)
3✔
5011
                if err != nil {
3✔
5012
                        return nil, err
×
5013
                }
×
5014

5015
                channel.Resolutions = append(channel.Resolutions, rpcResolution)
3✔
5016
        }
5017

5018
        return channel, nil
3✔
5019
}
5020

5021
func rpcChannelResolution(report *channeldb.ResolverReport) (*lnrpc.Resolution,
5022
        error) {
3✔
5023

3✔
5024
        res := &lnrpc.Resolution{
3✔
5025
                AmountSat: uint64(report.Amount),
3✔
5026
                Outpoint:  lnrpc.MarshalOutPoint(&report.OutPoint),
3✔
5027
        }
3✔
5028

3✔
5029
        if report.SpendTxID != nil {
6✔
5030
                res.SweepTxid = report.SpendTxID.String()
3✔
5031
        }
3✔
5032

5033
        switch report.ResolverType {
3✔
5034
        case channeldb.ResolverTypeAnchor:
2✔
5035
                res.ResolutionType = lnrpc.ResolutionType_ANCHOR
2✔
5036

5037
        case channeldb.ResolverTypeIncomingHtlc:
2✔
5038
                res.ResolutionType = lnrpc.ResolutionType_INCOMING_HTLC
2✔
5039

5040
        case channeldb.ResolverTypeOutgoingHtlc:
3✔
5041
                res.ResolutionType = lnrpc.ResolutionType_OUTGOING_HTLC
3✔
5042

5043
        case channeldb.ResolverTypeCommit:
3✔
5044
                res.ResolutionType = lnrpc.ResolutionType_COMMIT
3✔
5045

5046
        default:
×
5047
                return nil, fmt.Errorf("unknown resolver type: %v",
×
5048
                        report.ResolverType)
×
5049
        }
5050

5051
        switch report.ResolverOutcome {
3✔
5052
        case channeldb.ResolverOutcomeClaimed:
3✔
5053
                res.Outcome = lnrpc.ResolutionOutcome_CLAIMED
3✔
5054

UNCOV
5055
        case channeldb.ResolverOutcomeUnclaimed:
×
UNCOV
5056
                res.Outcome = lnrpc.ResolutionOutcome_UNCLAIMED
×
5057

5058
        case channeldb.ResolverOutcomeAbandoned:
×
5059
                res.Outcome = lnrpc.ResolutionOutcome_ABANDONED
×
5060

5061
        case channeldb.ResolverOutcomeFirstStage:
3✔
5062
                res.Outcome = lnrpc.ResolutionOutcome_FIRST_STAGE
3✔
5063

5064
        case channeldb.ResolverOutcomeTimeout:
3✔
5065
                res.Outcome = lnrpc.ResolutionOutcome_TIMEOUT
3✔
5066

5067
        default:
×
5068
                return nil, fmt.Errorf("unknown outcome: %v",
×
5069
                        report.ResolverOutcome)
×
5070
        }
5071

5072
        return res, nil
3✔
5073
}
5074

5075
// getInitiators returns an initiator enum that provides information about the
5076
// party that initiated channel's open and close. This information is obtained
5077
// from the historical channel bucket, so unknown values are returned when the
5078
// channel is not present (which indicates that it was closed before we started
5079
// writing channels to the historical close bucket).
5080
func (r *rpcServer) getInitiators(chanPoint *wire.OutPoint) (
5081
        lnrpc.Initiator,
5082
        lnrpc.Initiator, error) {
3✔
5083

3✔
5084
        var (
3✔
5085
                openInitiator  = lnrpc.Initiator_INITIATOR_UNKNOWN
3✔
5086
                closeInitiator = lnrpc.Initiator_INITIATOR_UNKNOWN
3✔
5087
        )
3✔
5088

3✔
5089
        // To get the close initiator for cooperative closes, we need
3✔
5090
        // to get the channel status from the historical channel bucket.
3✔
5091
        histChan, err := r.server.chanStateDB.FetchHistoricalChannel(chanPoint)
3✔
5092
        switch {
3✔
5093
        // The node has upgraded from a version where we did not store
5094
        // historical channels, and has not closed a channel since. Do
5095
        // not return an error, initiator values are unknown.
5096
        case err == channeldb.ErrNoHistoricalBucket:
×
5097
                return openInitiator, closeInitiator, nil
×
5098

5099
        // The channel was closed before we started storing historical
5100
        // channels. Do  not return an error, initiator values are unknown.
5101
        case err == channeldb.ErrChannelNotFound:
×
5102
                return openInitiator, closeInitiator, nil
×
5103

5104
        case err != nil:
×
5105
                return 0, 0, err
×
5106
        }
5107

5108
        // If we successfully looked up the channel, determine initiator based
5109
        // on channels status.
5110
        if histChan.IsInitiator {
6✔
5111
                openInitiator = lnrpc.Initiator_INITIATOR_LOCAL
3✔
5112
        } else {
6✔
5113
                openInitiator = lnrpc.Initiator_INITIATOR_REMOTE
3✔
5114
        }
3✔
5115

5116
        localInit := histChan.HasChanStatus(
3✔
5117
                channeldb.ChanStatusLocalCloseInitiator,
3✔
5118
        )
3✔
5119

3✔
5120
        remoteInit := histChan.HasChanStatus(
3✔
5121
                channeldb.ChanStatusRemoteCloseInitiator,
3✔
5122
        )
3✔
5123

3✔
5124
        switch {
3✔
5125
        // There is a possible case where closes were attempted by both parties.
5126
        // We return the initiator as both in this case to provide full
5127
        // information about the close.
5128
        case localInit && remoteInit:
×
5129
                closeInitiator = lnrpc.Initiator_INITIATOR_BOTH
×
5130

5131
        case localInit:
3✔
5132
                closeInitiator = lnrpc.Initiator_INITIATOR_LOCAL
3✔
5133

5134
        case remoteInit:
3✔
5135
                closeInitiator = lnrpc.Initiator_INITIATOR_REMOTE
3✔
5136
        }
5137

5138
        return openInitiator, closeInitiator, nil
3✔
5139
}
5140

5141
// SubscribeChannelEvents returns a uni-directional stream (server -> client)
5142
// for notifying the client of newly active, inactive or closed channels.
5143
func (r *rpcServer) SubscribeChannelEvents(req *lnrpc.ChannelEventSubscription,
5144
        updateStream lnrpc.Lightning_SubscribeChannelEventsServer) error {
3✔
5145

3✔
5146
        channelEventSub, err := r.server.channelNotifier.SubscribeChannelEvents()
3✔
5147
        if err != nil {
3✔
5148
                return err
×
5149
        }
×
5150

5151
        // Ensure that the resources for the client is cleaned up once either
5152
        // the server, or client exits.
5153
        defer channelEventSub.Cancel()
3✔
5154

3✔
5155
        for {
6✔
5156
                select {
3✔
5157
                // A new update has been sent by the channel router, we'll
5158
                // marshal it into the form expected by the gRPC client, then
5159
                // send it off to the client(s).
5160
                case e := <-channelEventSub.Updates():
3✔
5161
                        var update *lnrpc.ChannelEventUpdate
3✔
5162
                        switch event := e.(type) {
3✔
5163
                        case channelnotifier.PendingOpenChannelEvent:
3✔
5164
                                update = &lnrpc.ChannelEventUpdate{
3✔
5165
                                        Type: lnrpc.ChannelEventUpdate_PENDING_OPEN_CHANNEL,
3✔
5166
                                        Channel: &lnrpc.ChannelEventUpdate_PendingOpenChannel{
3✔
5167
                                                PendingOpenChannel: &lnrpc.PendingUpdate{
3✔
5168
                                                        Txid:        event.ChannelPoint.Hash[:],
3✔
5169
                                                        OutputIndex: event.ChannelPoint.Index,
3✔
5170
                                                },
3✔
5171
                                        },
3✔
5172
                                }
3✔
5173
                        case channelnotifier.OpenChannelEvent:
3✔
5174
                                channel, err := createRPCOpenChannel(
3✔
5175
                                        r, event.Channel, true, false,
3✔
5176
                                )
3✔
5177
                                if err != nil {
3✔
5178
                                        return err
×
5179
                                }
×
5180

5181
                                update = &lnrpc.ChannelEventUpdate{
3✔
5182
                                        Type: lnrpc.ChannelEventUpdate_OPEN_CHANNEL,
3✔
5183
                                        Channel: &lnrpc.ChannelEventUpdate_OpenChannel{
3✔
5184
                                                OpenChannel: channel,
3✔
5185
                                        },
3✔
5186
                                }
3✔
5187

5188
                        case channelnotifier.ClosedChannelEvent:
3✔
5189
                                closedChannel, err := r.createRPCClosedChannel(
3✔
5190
                                        event.CloseSummary,
3✔
5191
                                )
3✔
5192
                                if err != nil {
3✔
5193
                                        return err
×
5194
                                }
×
5195

5196
                                update = &lnrpc.ChannelEventUpdate{
3✔
5197
                                        Type: lnrpc.ChannelEventUpdate_CLOSED_CHANNEL,
3✔
5198
                                        Channel: &lnrpc.ChannelEventUpdate_ClosedChannel{
3✔
5199
                                                ClosedChannel: closedChannel,
3✔
5200
                                        },
3✔
5201
                                }
3✔
5202

5203
                        case channelnotifier.ActiveChannelEvent:
3✔
5204
                                update = &lnrpc.ChannelEventUpdate{
3✔
5205
                                        Type: lnrpc.ChannelEventUpdate_ACTIVE_CHANNEL,
3✔
5206
                                        Channel: &lnrpc.ChannelEventUpdate_ActiveChannel{
3✔
5207
                                                ActiveChannel: &lnrpc.ChannelPoint{
3✔
5208
                                                        FundingTxid: &lnrpc.ChannelPoint_FundingTxidBytes{
3✔
5209
                                                                FundingTxidBytes: event.ChannelPoint.Hash[:],
3✔
5210
                                                        },
3✔
5211
                                                        OutputIndex: event.ChannelPoint.Index,
3✔
5212
                                                },
3✔
5213
                                        },
3✔
5214
                                }
3✔
5215

5216
                        case channelnotifier.InactiveChannelEvent:
3✔
5217
                                update = &lnrpc.ChannelEventUpdate{
3✔
5218
                                        Type: lnrpc.ChannelEventUpdate_INACTIVE_CHANNEL,
3✔
5219
                                        Channel: &lnrpc.ChannelEventUpdate_InactiveChannel{
3✔
5220
                                                InactiveChannel: &lnrpc.ChannelPoint{
3✔
5221
                                                        FundingTxid: &lnrpc.ChannelPoint_FundingTxidBytes{
3✔
5222
                                                                FundingTxidBytes: event.ChannelPoint.Hash[:],
3✔
5223
                                                        },
3✔
5224
                                                        OutputIndex: event.ChannelPoint.Index,
3✔
5225
                                                },
3✔
5226
                                        },
3✔
5227
                                }
3✔
5228

5229
                        // Completely ignore ActiveLinkEvent and
5230
                        // InactiveLinkEvent as this is explicitly not exposed
5231
                        // to the RPC.
5232
                        case channelnotifier.ActiveLinkEvent,
5233
                                channelnotifier.InactiveLinkEvent:
3✔
5234

3✔
5235
                                continue
3✔
5236

5237
                        case channelnotifier.FullyResolvedChannelEvent:
3✔
5238
                                update = &lnrpc.ChannelEventUpdate{
3✔
5239
                                        Type: lnrpc.ChannelEventUpdate_FULLY_RESOLVED_CHANNEL,
3✔
5240
                                        Channel: &lnrpc.ChannelEventUpdate_FullyResolvedChannel{
3✔
5241
                                                FullyResolvedChannel: &lnrpc.ChannelPoint{
3✔
5242
                                                        FundingTxid: &lnrpc.ChannelPoint_FundingTxidBytes{
3✔
5243
                                                                FundingTxidBytes: event.ChannelPoint.Hash[:],
3✔
5244
                                                        },
3✔
5245
                                                        OutputIndex: event.ChannelPoint.Index,
3✔
5246
                                                },
3✔
5247
                                        },
3✔
5248
                                }
3✔
5249

5250
                        default:
×
5251
                                return fmt.Errorf("unexpected channel event update: %v", event)
×
5252
                        }
5253

5254
                        if err := updateStream.Send(update); err != nil {
3✔
5255
                                return err
×
5256
                        }
×
5257

5258
                // The response stream's context for whatever reason has been
5259
                // closed. If context is closed by an exceeded deadline we will
5260
                // return an error.
5261
                case <-updateStream.Context().Done():
3✔
5262
                        if errors.Is(updateStream.Context().Err(), context.Canceled) {
6✔
5263
                                return nil
3✔
5264
                        }
3✔
5265
                        return updateStream.Context().Err()
×
5266

5267
                case <-r.quit:
×
5268
                        return nil
×
5269
                }
5270
        }
5271
}
5272

5273
// paymentStream enables different types of payment streams, such as:
5274
// lnrpc.Lightning_SendPaymentServer and lnrpc.Lightning_SendToRouteServer to
5275
// execute sendPayment. We use this struct as a sort of bridge to enable code
5276
// re-use between SendPayment and SendToRoute.
5277
type paymentStream struct {
5278
        recv func() (*rpcPaymentRequest, error)
5279
        send func(*lnrpc.SendResponse) error
5280
}
5281

5282
// rpcPaymentRequest wraps lnrpc.SendRequest so that routes from
5283
// lnrpc.SendToRouteRequest can be passed to sendPayment.
5284
type rpcPaymentRequest struct {
5285
        *lnrpc.SendRequest
5286
        route *route.Route
5287
}
5288

5289
// SendPayment dispatches a bi-directional streaming RPC for sending payments
5290
// through the Lightning Network. A single RPC invocation creates a persistent
5291
// bi-directional stream allowing clients to rapidly send payments through the
5292
// Lightning Network with a single persistent connection.
5293
func (r *rpcServer) SendPayment(stream lnrpc.Lightning_SendPaymentServer) error {
×
5294
        var lock sync.Mutex
×
5295

×
5296
        return r.sendPayment(&paymentStream{
×
5297
                recv: func() (*rpcPaymentRequest, error) {
×
5298
                        req, err := stream.Recv()
×
5299
                        if err != nil {
×
5300
                                return nil, err
×
5301
                        }
×
5302

5303
                        return &rpcPaymentRequest{
×
5304
                                SendRequest: req,
×
5305
                        }, nil
×
5306
                },
5307
                send: func(r *lnrpc.SendResponse) error {
×
5308
                        // Calling stream.Send concurrently is not safe.
×
5309
                        lock.Lock()
×
5310
                        defer lock.Unlock()
×
5311
                        return stream.Send(r)
×
5312
                },
×
5313
        })
5314
}
5315

5316
// SendToRoute dispatches a bi-directional streaming RPC for sending payments
5317
// through the Lightning Network via predefined routes passed in. A single RPC
5318
// invocation creates a persistent bi-directional stream allowing clients to
5319
// rapidly send payments through the Lightning Network with a single persistent
5320
// connection.
5321
func (r *rpcServer) SendToRoute(stream lnrpc.Lightning_SendToRouteServer) error {
3✔
5322
        var lock sync.Mutex
3✔
5323

3✔
5324
        return r.sendPayment(&paymentStream{
3✔
5325
                recv: func() (*rpcPaymentRequest, error) {
6✔
5326
                        req, err := stream.Recv()
3✔
5327
                        if err != nil {
6✔
5328
                                return nil, err
3✔
5329
                        }
3✔
5330

5331
                        return r.unmarshallSendToRouteRequest(req)
3✔
5332
                },
5333
                send: func(r *lnrpc.SendResponse) error {
3✔
5334
                        // Calling stream.Send concurrently is not safe.
3✔
5335
                        lock.Lock()
3✔
5336
                        defer lock.Unlock()
3✔
5337
                        return stream.Send(r)
3✔
5338
                },
3✔
5339
        })
5340
}
5341

5342
// unmarshallSendToRouteRequest unmarshalls an rpc sendtoroute request
5343
func (r *rpcServer) unmarshallSendToRouteRequest(
5344
        req *lnrpc.SendToRouteRequest) (*rpcPaymentRequest, error) {
3✔
5345

3✔
5346
        if req.Route == nil {
3✔
5347
                return nil, fmt.Errorf("unable to send, no route provided")
×
5348
        }
×
5349

5350
        route, err := r.routerBackend.UnmarshallRoute(req.Route)
3✔
5351
        if err != nil {
3✔
5352
                return nil, err
×
5353
        }
×
5354

5355
        return &rpcPaymentRequest{
3✔
5356
                SendRequest: &lnrpc.SendRequest{
3✔
5357
                        PaymentHash:       req.PaymentHash,
3✔
5358
                        PaymentHashString: req.PaymentHashString,
3✔
5359
                },
3✔
5360
                route: route,
3✔
5361
        }, nil
3✔
5362
}
5363

5364
// rpcPaymentIntent is a small wrapper struct around the of values we can
5365
// receive from a client over RPC if they wish to send a payment. We'll either
5366
// extract these fields from a payment request (which may include routing
5367
// hints), or we'll get a fully populated route from the user that we'll pass
5368
// directly to the channel router for dispatching.
5369
type rpcPaymentIntent struct {
5370
        msat               lnwire.MilliSatoshi
5371
        feeLimit           lnwire.MilliSatoshi
5372
        cltvLimit          uint32
5373
        dest               route.Vertex
5374
        rHash              [32]byte
5375
        cltvDelta          uint16
5376
        routeHints         [][]zpay32.HopHint
5377
        outgoingChannelIDs []uint64
5378
        lastHop            *route.Vertex
5379
        destFeatures       *lnwire.FeatureVector
5380
        paymentAddr        fn.Option[[32]byte]
5381
        payReq             []byte
5382
        metadata           []byte
5383
        blindedPathSet     *routing.BlindedPaymentPathSet
5384

5385
        destCustomRecords record.CustomSet
5386

5387
        route *route.Route
5388
}
5389

5390
// extractPaymentIntent attempts to parse the complete details required to
5391
// dispatch a client from the information presented by an RPC client. There are
5392
// three ways a client can specify their payment details: a payment request,
5393
// via manual details, or via a complete route.
5394
func (r *rpcServer) extractPaymentIntent(rpcPayReq *rpcPaymentRequest) (rpcPaymentIntent, error) {
3✔
5395
        payIntent := rpcPaymentIntent{}
3✔
5396

3✔
5397
        // If a route was specified, then we can use that directly.
3✔
5398
        if rpcPayReq.route != nil {
6✔
5399
                // If the user is using the REST interface, then they'll be
3✔
5400
                // passing the payment hash as a hex encoded string.
3✔
5401
                if rpcPayReq.PaymentHashString != "" {
3✔
5402
                        paymentHash, err := hex.DecodeString(
×
5403
                                rpcPayReq.PaymentHashString,
×
5404
                        )
×
5405
                        if err != nil {
×
5406
                                return payIntent, err
×
5407
                        }
×
5408

5409
                        copy(payIntent.rHash[:], paymentHash)
×
5410
                } else {
3✔
5411
                        copy(payIntent.rHash[:], rpcPayReq.PaymentHash)
3✔
5412
                }
3✔
5413

5414
                payIntent.route = rpcPayReq.route
3✔
5415
                return payIntent, nil
3✔
5416
        }
5417

5418
        // If there are no routes specified, pass along a outgoing channel
5419
        // restriction if specified. The main server rpc does not support
5420
        // multiple channel restrictions.
5421
        if rpcPayReq.OutgoingChanId != 0 {
×
5422
                payIntent.outgoingChannelIDs = []uint64{
×
5423
                        rpcPayReq.OutgoingChanId,
×
5424
                }
×
5425
        }
×
5426

5427
        // Pass along a last hop restriction if specified.
5428
        if len(rpcPayReq.LastHopPubkey) > 0 {
×
5429
                lastHop, err := route.NewVertexFromBytes(
×
5430
                        rpcPayReq.LastHopPubkey,
×
5431
                )
×
5432
                if err != nil {
×
5433
                        return payIntent, err
×
5434
                }
×
5435
                payIntent.lastHop = &lastHop
×
5436
        }
5437

5438
        // Take the CLTV limit from the request if set, otherwise use the max.
5439
        cltvLimit, err := routerrpc.ValidateCLTVLimit(
×
5440
                rpcPayReq.CltvLimit, r.cfg.MaxOutgoingCltvExpiry,
×
5441
        )
×
5442
        if err != nil {
×
5443
                return payIntent, err
×
5444
        }
×
5445
        payIntent.cltvLimit = cltvLimit
×
5446

×
5447
        customRecords := record.CustomSet(rpcPayReq.DestCustomRecords)
×
5448
        if err := customRecords.Validate(); err != nil {
×
5449
                return payIntent, err
×
5450
        }
×
5451
        payIntent.destCustomRecords = customRecords
×
5452

×
5453
        validateDest := func(dest route.Vertex) error {
×
5454
                if rpcPayReq.AllowSelfPayment {
×
5455
                        return nil
×
5456
                }
×
5457

5458
                if dest == r.selfNode {
×
5459
                        return errors.New("self-payments not allowed")
×
5460
                }
×
5461

5462
                return nil
×
5463
        }
5464

5465
        // If the payment request field isn't blank, then the details of the
5466
        // invoice are encoded entirely within the encoded payReq.  So we'll
5467
        // attempt to decode it, populating the payment accordingly.
5468
        if rpcPayReq.PaymentRequest != "" {
×
5469
                payReq, err := zpay32.Decode(
×
5470
                        rpcPayReq.PaymentRequest, r.cfg.ActiveNetParams.Params,
×
5471
                        zpay32.WithErrorOnUnknownFeatureBit(),
×
5472
                )
×
5473
                if err != nil {
×
5474
                        return payIntent, err
×
5475
                }
×
5476

5477
                // Next, we'll ensure that this payreq hasn't already expired.
5478
                err = routerrpc.ValidatePayReqExpiry(payReq)
×
5479
                if err != nil {
×
5480
                        return payIntent, err
×
5481
                }
×
5482

5483
                // If the amount was not included in the invoice, then we let
5484
                // the payer specify the amount of satoshis they wish to send.
5485
                // We override the amount to pay with the amount provided from
5486
                // the payment request.
5487
                if payReq.MilliSat == nil {
×
5488
                        amt, err := lnrpc.UnmarshallAmt(
×
5489
                                rpcPayReq.Amt, rpcPayReq.AmtMsat,
×
5490
                        )
×
5491
                        if err != nil {
×
5492
                                return payIntent, err
×
5493
                        }
×
5494
                        if amt == 0 {
×
5495
                                return payIntent, errors.New("amount must be " +
×
5496
                                        "specified when paying a zero amount " +
×
5497
                                        "invoice")
×
5498
                        }
×
5499

5500
                        payIntent.msat = amt
×
5501
                } else {
×
5502
                        payIntent.msat = *payReq.MilliSat
×
5503
                }
×
5504

5505
                // Calculate the fee limit that should be used for this payment.
5506
                payIntent.feeLimit = lnrpc.CalculateFeeLimit(
×
5507
                        rpcPayReq.FeeLimit, payIntent.msat,
×
5508
                )
×
5509

×
5510
                copy(payIntent.rHash[:], payReq.PaymentHash[:])
×
5511
                destKey := payReq.Destination.SerializeCompressed()
×
5512
                copy(payIntent.dest[:], destKey)
×
5513
                payIntent.cltvDelta = uint16(payReq.MinFinalCLTVExpiry())
×
5514
                payIntent.routeHints = payReq.RouteHints
×
5515
                payIntent.payReq = []byte(rpcPayReq.PaymentRequest)
×
5516
                payIntent.destFeatures = payReq.Features
×
5517
                payIntent.paymentAddr = payReq.PaymentAddr
×
5518
                payIntent.metadata = payReq.Metadata
×
5519

×
5520
                if len(payReq.BlindedPaymentPaths) > 0 {
×
5521
                        pathSet, err := routerrpc.BuildBlindedPathSet(
×
5522
                                payReq.BlindedPaymentPaths,
×
5523
                        )
×
5524
                        if err != nil {
×
5525
                                return payIntent, err
×
5526
                        }
×
5527
                        payIntent.blindedPathSet = pathSet
×
5528

×
5529
                        // Replace the destination node with the target public
×
5530
                        // key of the blinded path set.
×
5531
                        copy(
×
5532
                                payIntent.dest[:],
×
5533
                                pathSet.TargetPubKey().SerializeCompressed(),
×
5534
                        )
×
5535

×
5536
                        pathFeatures := pathSet.Features()
×
5537
                        if !pathFeatures.IsEmpty() {
×
5538
                                payIntent.destFeatures = pathFeatures.Clone()
×
5539
                        }
×
5540
                }
5541

5542
                if err := validateDest(payIntent.dest); err != nil {
×
5543
                        return payIntent, err
×
5544
                }
×
5545

5546
                // Do bounds checking with the block padding.
5547
                err = routing.ValidateCLTVLimit(
×
5548
                        payIntent.cltvLimit, payIntent.cltvDelta, true,
×
5549
                )
×
5550
                if err != nil {
×
5551
                        return payIntent, err
×
5552
                }
×
5553

5554
                return payIntent, nil
×
5555
        }
5556

5557
        // At this point, a destination MUST be specified, so we'll convert it
5558
        // into the proper representation now. The destination will either be
5559
        // encoded as raw bytes, or via a hex string.
5560
        var pubBytes []byte
×
5561
        if len(rpcPayReq.Dest) != 0 {
×
5562
                pubBytes = rpcPayReq.Dest
×
5563
        } else {
×
5564
                var err error
×
5565
                pubBytes, err = hex.DecodeString(rpcPayReq.DestString)
×
5566
                if err != nil {
×
5567
                        return payIntent, err
×
5568
                }
×
5569
        }
5570
        if len(pubBytes) != 33 {
×
5571
                return payIntent, errors.New("invalid key length")
×
5572
        }
×
5573
        copy(payIntent.dest[:], pubBytes)
×
5574

×
5575
        if err := validateDest(payIntent.dest); err != nil {
×
5576
                return payIntent, err
×
5577
        }
×
5578

5579
        // Payment address may not be needed by legacy invoices.
5580
        if len(rpcPayReq.PaymentAddr) != 0 && len(rpcPayReq.PaymentAddr) != 32 {
×
5581
                return payIntent, errors.New("invalid payment address length")
×
5582
        }
×
5583

5584
        // Set the payment address if it was explicitly defined with the
5585
        // rpcPaymentRequest.
5586
        // Note that the payment address for the payIntent should be nil if none
5587
        // was provided with the rpcPaymentRequest.
5588
        if len(rpcPayReq.PaymentAddr) != 0 {
×
5589
                var addr [32]byte
×
5590
                copy(addr[:], rpcPayReq.PaymentAddr)
×
5591
                payIntent.paymentAddr = fn.Some(addr)
×
5592
        }
×
5593

5594
        // Otherwise, If the payment request field was not specified
5595
        // (and a custom route wasn't specified), construct the payment
5596
        // from the other fields.
5597
        payIntent.msat, err = lnrpc.UnmarshallAmt(
×
5598
                rpcPayReq.Amt, rpcPayReq.AmtMsat,
×
5599
        )
×
5600
        if err != nil {
×
5601
                return payIntent, err
×
5602
        }
×
5603

5604
        // Calculate the fee limit that should be used for this payment.
5605
        payIntent.feeLimit = lnrpc.CalculateFeeLimit(
×
5606
                rpcPayReq.FeeLimit, payIntent.msat,
×
5607
        )
×
5608

×
5609
        if rpcPayReq.FinalCltvDelta != 0 {
×
5610
                payIntent.cltvDelta = uint16(rpcPayReq.FinalCltvDelta)
×
5611
        } else {
×
5612
                // If no final cltv delta is given, assume the default that we
×
5613
                // use when creating an invoice. We do not assume the default of
×
5614
                // 9 blocks that is defined in BOLT-11, because this is never
×
5615
                // enough for other lnd nodes.
×
5616
                payIntent.cltvDelta = uint16(r.cfg.Bitcoin.TimeLockDelta)
×
5617
        }
×
5618

5619
        // Do bounds checking with the block padding so the router isn't left
5620
        // with a zombie payment in case the user messes up.
5621
        err = routing.ValidateCLTVLimit(
×
5622
                payIntent.cltvLimit, payIntent.cltvDelta, true,
×
5623
        )
×
5624
        if err != nil {
×
5625
                return payIntent, err
×
5626
        }
×
5627

5628
        // If the user is manually specifying payment details, then the payment
5629
        // hash may be encoded as a string.
5630
        switch {
×
5631
        case rpcPayReq.PaymentHashString != "":
×
5632
                paymentHash, err := hex.DecodeString(
×
5633
                        rpcPayReq.PaymentHashString,
×
5634
                )
×
5635
                if err != nil {
×
5636
                        return payIntent, err
×
5637
                }
×
5638

5639
                copy(payIntent.rHash[:], paymentHash)
×
5640

5641
        default:
×
5642
                copy(payIntent.rHash[:], rpcPayReq.PaymentHash)
×
5643
        }
5644

5645
        // Unmarshal any custom destination features.
5646
        payIntent.destFeatures, err = routerrpc.UnmarshalFeatures(
×
5647
                rpcPayReq.DestFeatures,
×
5648
        )
×
5649
        if err != nil {
×
5650
                return payIntent, err
×
5651
        }
×
5652

5653
        return payIntent, nil
×
5654
}
5655

5656
type paymentIntentResponse struct {
5657
        Route    *route.Route
5658
        Preimage [32]byte
5659
        Err      error
5660
}
5661

5662
// dispatchPaymentIntent attempts to fully dispatch an RPC payment intent.
5663
// We'll either pass the payment as a whole to the channel router, or give it a
5664
// pre-built route. The first error this method returns denotes if we were
5665
// unable to save the payment. The second error returned denotes if the payment
5666
// didn't succeed.
5667
func (r *rpcServer) dispatchPaymentIntent(
5668
        payIntent *rpcPaymentIntent) (*paymentIntentResponse, error) {
3✔
5669

3✔
5670
        // Construct a payment request to send to the channel router. If the
3✔
5671
        // payment is successful, the route chosen will be returned. Otherwise,
3✔
5672
        // we'll get a non-nil error.
3✔
5673
        var (
3✔
5674
                preImage  [32]byte
3✔
5675
                route     *route.Route
3✔
5676
                routerErr error
3✔
5677
        )
3✔
5678

3✔
5679
        // If a route was specified, then we'll pass the route directly to the
3✔
5680
        // router, otherwise we'll create a payment session to execute it.
3✔
5681
        if payIntent.route == nil {
3✔
5682
                payment := &routing.LightningPayment{
×
5683
                        Target:             payIntent.dest,
×
5684
                        Amount:             payIntent.msat,
×
5685
                        FinalCLTVDelta:     payIntent.cltvDelta,
×
5686
                        FeeLimit:           payIntent.feeLimit,
×
5687
                        CltvLimit:          payIntent.cltvLimit,
×
5688
                        RouteHints:         payIntent.routeHints,
×
5689
                        OutgoingChannelIDs: payIntent.outgoingChannelIDs,
×
5690
                        LastHop:            payIntent.lastHop,
×
5691
                        PaymentRequest:     payIntent.payReq,
×
5692
                        PayAttemptTimeout:  routing.DefaultPayAttemptTimeout,
×
5693
                        DestCustomRecords:  payIntent.destCustomRecords,
×
5694
                        DestFeatures:       payIntent.destFeatures,
×
5695
                        PaymentAddr:        payIntent.paymentAddr,
×
5696
                        Metadata:           payIntent.metadata,
×
5697
                        BlindedPathSet:     payIntent.blindedPathSet,
×
5698

×
5699
                        // Don't enable multi-part payments on the main rpc.
×
5700
                        // Users need to use routerrpc for that.
×
5701
                        MaxParts: 1,
×
5702
                }
×
5703
                err := payment.SetPaymentHash(payIntent.rHash)
×
5704
                if err != nil {
×
5705
                        return nil, err
×
5706
                }
×
5707

5708
                preImage, route, routerErr = r.server.chanRouter.SendPayment(
×
5709
                        payment,
×
5710
                )
×
5711
        } else {
3✔
5712
                var attempt *channeldb.HTLCAttempt
3✔
5713
                attempt, routerErr = r.server.chanRouter.SendToRoute(
3✔
5714
                        payIntent.rHash, payIntent.route, nil,
3✔
5715
                )
3✔
5716

3✔
5717
                if routerErr == nil {
6✔
5718
                        preImage = attempt.Settle.Preimage
3✔
5719
                }
3✔
5720

5721
                route = payIntent.route
3✔
5722
        }
5723

5724
        // If the route failed, then we'll return a nil save err, but a non-nil
5725
        // routing err.
5726
        if routerErr != nil {
6✔
5727
                rpcsLog.Warnf("Unable to send payment: %v", routerErr)
3✔
5728

3✔
5729
                return &paymentIntentResponse{
3✔
5730
                        Err: routerErr,
3✔
5731
                }, nil
3✔
5732
        }
3✔
5733

5734
        return &paymentIntentResponse{
3✔
5735
                Route:    route,
3✔
5736
                Preimage: preImage,
3✔
5737
        }, nil
3✔
5738
}
5739

5740
// sendPayment takes a paymentStream (a source of pre-built routes or payment
5741
// requests) and continually attempt to dispatch payment requests written to
5742
// the write end of the stream. Responses will also be streamed back to the
5743
// client via the write end of the stream. This method is by both SendToRoute
5744
// and SendPayment as the logic is virtually identical.
5745
func (r *rpcServer) sendPayment(stream *paymentStream) error {
3✔
5746
        payChan := make(chan *rpcPaymentIntent)
3✔
5747
        errChan := make(chan error, 1)
3✔
5748

3✔
5749
        // We don't allow payments to be sent while the daemon itself is still
3✔
5750
        // syncing as we may be trying to sent a payment over a "stale"
3✔
5751
        // channel.
3✔
5752
        if !r.server.Started() {
3✔
5753
                return ErrServerNotActive
×
5754
        }
×
5755

5756
        // TODO(roasbeef): check payment filter to see if already used?
5757

5758
        // In order to limit the level of concurrency and prevent a client from
5759
        // attempting to OOM the server, we'll set up a semaphore to create an
5760
        // upper ceiling on the number of outstanding payments.
5761
        const numOutstandingPayments = 2000
3✔
5762
        htlcSema := make(chan struct{}, numOutstandingPayments)
3✔
5763
        for i := 0; i < numOutstandingPayments; i++ {
6✔
5764
                htlcSema <- struct{}{}
3✔
5765
        }
3✔
5766

5767
        // We keep track of the running goroutines and set up a quit signal we
5768
        // can use to request them to exit if the method returns because of an
5769
        // encountered error.
5770
        var wg sync.WaitGroup
3✔
5771
        reqQuit := make(chan struct{})
3✔
5772
        defer close(reqQuit)
3✔
5773

3✔
5774
        // Launch a new goroutine to handle reading new payment requests from
3✔
5775
        // the client. This way we can handle errors independently of blocking
3✔
5776
        // and waiting for the next payment request to come through.
3✔
5777
        // TODO(joostjager): Callers expect result to come in in the same order
3✔
5778
        // as the request were sent, but this is far from guarantueed in the
3✔
5779
        // code below.
3✔
5780
        wg.Add(1)
3✔
5781
        go func() {
6✔
5782
                defer wg.Done()
3✔
5783

3✔
5784
                for {
6✔
5785
                        select {
3✔
5786
                        case <-reqQuit:
×
5787
                                return
×
5788

5789
                        default:
3✔
5790
                                // Receive the next pending payment within the
3✔
5791
                                // stream sent by the client. If we read the
3✔
5792
                                // EOF sentinel, then the client has closed the
3✔
5793
                                // stream, and we can exit normally.
3✔
5794
                                nextPayment, err := stream.recv()
3✔
5795
                                if err == io.EOF {
3✔
5796
                                        close(payChan)
×
5797
                                        return
×
5798
                                } else if err != nil {
6✔
5799
                                        rpcsLog.Errorf("Failed receiving from "+
3✔
5800
                                                "stream: %v", err)
3✔
5801

3✔
5802
                                        select {
3✔
5803
                                        case errChan <- err:
3✔
5804
                                        default:
×
5805
                                        }
5806
                                        return
3✔
5807
                                }
5808

5809
                                // Populate the next payment, either from the
5810
                                // payment request, or from the explicitly set
5811
                                // fields. If the payment proto wasn't well
5812
                                // formed, then we'll send an error reply and
5813
                                // wait for the next payment.
5814
                                payIntent, err := r.extractPaymentIntent(
3✔
5815
                                        nextPayment,
3✔
5816
                                )
3✔
5817
                                if err != nil {
3✔
5818
                                        if err := stream.send(&lnrpc.SendResponse{
×
5819
                                                PaymentError: err.Error(),
×
5820
                                                PaymentHash:  payIntent.rHash[:],
×
5821
                                        }); err != nil {
×
5822
                                                rpcsLog.Errorf("Failed "+
×
5823
                                                        "sending on "+
×
5824
                                                        "stream: %v", err)
×
5825

×
5826
                                                select {
×
5827
                                                case errChan <- err:
×
5828
                                                default:
×
5829
                                                }
5830
                                                return
×
5831
                                        }
5832
                                        continue
×
5833
                                }
5834

5835
                                // If the payment was well formed, then we'll
5836
                                // send to the dispatch goroutine, or exit,
5837
                                // which ever comes first.
5838
                                select {
3✔
5839
                                case payChan <- &payIntent:
3✔
5840
                                case <-reqQuit:
×
5841
                                        return
×
5842
                                }
5843
                        }
5844
                }
5845
        }()
5846

5847
sendLoop:
3✔
5848
        for {
6✔
5849
                select {
3✔
5850

5851
                // If we encounter and error either during sending or
5852
                // receiving, we return directly, closing the stream.
5853
                case err := <-errChan:
3✔
5854
                        return err
3✔
5855

5856
                case <-r.quit:
×
5857
                        return errors.New("rpc server shutting down")
×
5858

5859
                case payIntent, ok := <-payChan:
3✔
5860
                        // If the receive loop is done, we break the send loop
3✔
5861
                        // and wait for the ongoing payments to finish before
3✔
5862
                        // exiting.
3✔
5863
                        if !ok {
3✔
5864
                                break sendLoop
×
5865
                        }
5866

5867
                        // We launch a new goroutine to execute the current
5868
                        // payment so we can continue to serve requests while
5869
                        // this payment is being dispatched.
5870
                        wg.Add(1)
3✔
5871
                        go func(payIntent *rpcPaymentIntent) {
6✔
5872
                                defer wg.Done()
3✔
5873

3✔
5874
                                // Attempt to grab a free semaphore slot, using
3✔
5875
                                // a defer to eventually release the slot
3✔
5876
                                // regardless of payment success.
3✔
5877
                                select {
3✔
5878
                                case <-htlcSema:
3✔
5879
                                case <-reqQuit:
×
5880
                                        return
×
5881
                                }
5882
                                defer func() {
6✔
5883
                                        htlcSema <- struct{}{}
3✔
5884
                                }()
3✔
5885

5886
                                resp, saveErr := r.dispatchPaymentIntent(
3✔
5887
                                        payIntent,
3✔
5888
                                )
3✔
5889

3✔
5890
                                switch {
3✔
5891
                                // If we were unable to save the state of the
5892
                                // payment, then we'll return the error to the
5893
                                // user, and terminate.
5894
                                case saveErr != nil:
×
5895
                                        rpcsLog.Errorf("Failed dispatching "+
×
5896
                                                "payment intent: %v", saveErr)
×
5897

×
5898
                                        select {
×
5899
                                        case errChan <- saveErr:
×
5900
                                        default:
×
5901
                                        }
5902
                                        return
×
5903

5904
                                // If we receive payment error than, instead of
5905
                                // terminating the stream, send error response
5906
                                // to the user.
5907
                                case resp.Err != nil:
3✔
5908
                                        err := stream.send(&lnrpc.SendResponse{
3✔
5909
                                                PaymentError: resp.Err.Error(),
3✔
5910
                                                PaymentHash:  payIntent.rHash[:],
3✔
5911
                                        })
3✔
5912
                                        if err != nil {
3✔
5913
                                                rpcsLog.Errorf("Failed "+
×
5914
                                                        "sending error "+
×
5915
                                                        "response: %v", err)
×
5916

×
5917
                                                select {
×
5918
                                                case errChan <- err:
×
5919
                                                default:
×
5920
                                                }
5921
                                        }
5922
                                        return
3✔
5923
                                }
5924

5925
                                backend := r.routerBackend
3✔
5926
                                marshalledRouted, err := backend.MarshallRoute(
3✔
5927
                                        resp.Route,
3✔
5928
                                )
3✔
5929
                                if err != nil {
3✔
5930
                                        errChan <- err
×
5931
                                        return
×
5932
                                }
×
5933

5934
                                err = stream.send(&lnrpc.SendResponse{
3✔
5935
                                        PaymentHash:     payIntent.rHash[:],
3✔
5936
                                        PaymentPreimage: resp.Preimage[:],
3✔
5937
                                        PaymentRoute:    marshalledRouted,
3✔
5938
                                })
3✔
5939
                                if err != nil {
3✔
5940
                                        rpcsLog.Errorf("Failed sending "+
×
5941
                                                "response: %v", err)
×
5942

×
5943
                                        select {
×
5944
                                        case errChan <- err:
×
5945
                                        default:
×
5946
                                        }
5947
                                        return
×
5948
                                }
5949
                        }(payIntent)
5950
                }
5951
        }
5952

5953
        // Wait for all goroutines to finish before closing the stream.
5954
        wg.Wait()
×
5955
        return nil
×
5956
}
5957

5958
// SendPaymentSync is the synchronous non-streaming version of SendPayment.
5959
// This RPC is intended to be consumed by clients of the REST proxy.
5960
// Additionally, this RPC expects the destination's public key and the payment
5961
// hash (if any) to be encoded as hex strings.
5962
func (r *rpcServer) SendPaymentSync(ctx context.Context,
5963
        nextPayment *lnrpc.SendRequest) (*lnrpc.SendResponse, error) {
×
5964

×
5965
        return r.sendPaymentSync(&rpcPaymentRequest{
×
5966
                SendRequest: nextPayment,
×
5967
        })
×
5968
}
×
5969

5970
// SendToRouteSync is the synchronous non-streaming version of SendToRoute.
5971
// This RPC is intended to be consumed by clients of the REST proxy.
5972
// Additionally, this RPC expects the payment hash (if any) to be encoded as
5973
// hex strings.
5974
func (r *rpcServer) SendToRouteSync(ctx context.Context,
5975
        req *lnrpc.SendToRouteRequest) (*lnrpc.SendResponse, error) {
3✔
5976

3✔
5977
        if req.Route == nil {
3✔
5978
                return nil, fmt.Errorf("unable to send, no routes provided")
×
5979
        }
×
5980

5981
        paymentRequest, err := r.unmarshallSendToRouteRequest(req)
3✔
5982
        if err != nil {
3✔
5983
                return nil, err
×
5984
        }
×
5985

5986
        return r.sendPaymentSync(paymentRequest)
3✔
5987
}
5988

5989
// sendPaymentSync is the synchronous variant of sendPayment. It will block and
5990
// wait until the payment has been fully completed.
5991
func (r *rpcServer) sendPaymentSync(
5992
        nextPayment *rpcPaymentRequest) (*lnrpc.SendResponse, error) {
3✔
5993

3✔
5994
        // We don't allow payments to be sent while the daemon itself is still
3✔
5995
        // syncing as we may be trying to sent a payment over a "stale"
3✔
5996
        // channel.
3✔
5997
        if !r.server.Started() {
3✔
5998
                return nil, ErrServerNotActive
×
5999
        }
×
6000

6001
        // First we'll attempt to map the proto describing the next payment to
6002
        // an intent that we can pass to local sub-systems.
6003
        payIntent, err := r.extractPaymentIntent(nextPayment)
3✔
6004
        if err != nil {
3✔
6005
                return nil, err
×
6006
        }
×
6007

6008
        // With the payment validated, we'll now attempt to dispatch the
6009
        // payment.
6010
        resp, saveErr := r.dispatchPaymentIntent(&payIntent)
3✔
6011
        switch {
3✔
6012
        case saveErr != nil:
×
6013
                return nil, saveErr
×
6014

6015
        case resp.Err != nil:
×
6016
                return &lnrpc.SendResponse{
×
6017
                        PaymentError: resp.Err.Error(),
×
6018
                        PaymentHash:  payIntent.rHash[:],
×
6019
                }, nil
×
6020
        }
6021

6022
        rpcRoute, err := r.routerBackend.MarshallRoute(resp.Route)
3✔
6023
        if err != nil {
3✔
6024
                return nil, err
×
6025
        }
×
6026

6027
        return &lnrpc.SendResponse{
3✔
6028
                PaymentHash:     payIntent.rHash[:],
3✔
6029
                PaymentPreimage: resp.Preimage[:],
3✔
6030
                PaymentRoute:    rpcRoute,
3✔
6031
        }, nil
3✔
6032
}
6033

6034
// AddInvoice attempts to add a new invoice to the invoice database. Any
6035
// duplicated invoices are rejected, therefore all invoices *must* have a
6036
// unique payment preimage.
6037
func (r *rpcServer) AddInvoice(ctx context.Context,
6038
        invoice *lnrpc.Invoice) (*lnrpc.AddInvoiceResponse, error) {
3✔
6039

3✔
6040
        var (
3✔
6041
                defaultDelta = r.cfg.Bitcoin.TimeLockDelta
3✔
6042
                blindCfg     = invoice.BlindedPathConfig
3✔
6043
                blind        = invoice.IsBlinded
3✔
6044
        )
3✔
6045

3✔
6046
        globalBlindCfg := r.server.cfg.Routing.BlindedPaths
3✔
6047
        blindingRestrictions := &routing.BlindedPathRestrictions{
3✔
6048
                MinDistanceFromIntroNode: globalBlindCfg.MinNumRealHops,
3✔
6049
                NumHops:                  globalBlindCfg.NumHops,
3✔
6050
                MaxNumPaths:              globalBlindCfg.MaxNumPaths,
3✔
6051
                NodeOmissionSet:          fn.NewSet[route.Vertex](),
3✔
6052
        }
3✔
6053

3✔
6054
        if blindCfg != nil && !blind {
3✔
6055
                return nil, fmt.Errorf("blinded path config provided but " +
×
6056
                        "IsBlinded not set")
×
6057
        }
×
6058

6059
        if blind && blindCfg != nil {
6✔
6060
                if blindCfg.MinNumRealHops != nil {
6✔
6061
                        blindingRestrictions.MinDistanceFromIntroNode =
3✔
6062
                                uint8(*blindCfg.MinNumRealHops)
3✔
6063
                }
3✔
6064
                if blindCfg.NumHops != nil {
6✔
6065
                        blindingRestrictions.NumHops = uint8(*blindCfg.NumHops)
3✔
6066
                }
3✔
6067
                if blindCfg.MaxNumPaths != nil {
3✔
6068
                        blindingRestrictions.MaxNumPaths =
×
6069
                                uint8(*blindCfg.MaxNumPaths)
×
6070
                }
×
6071

6072
                for _, nodeIDBytes := range blindCfg.NodeOmissionList {
3✔
6073
                        vertex, err := route.NewVertexFromBytes(nodeIDBytes)
×
6074
                        if err != nil {
×
6075
                                return nil, err
×
6076
                        }
×
6077

6078
                        blindingRestrictions.NodeOmissionSet.Add(vertex)
×
6079
                }
6080
        }
6081

6082
        if blindingRestrictions.MinDistanceFromIntroNode >
3✔
6083
                blindingRestrictions.NumHops {
3✔
6084

×
6085
                return nil, fmt.Errorf("the minimum number of real " +
×
6086
                        "hops in a blinded path must be smaller than " +
×
6087
                        "or equal to the number of hops expected to " +
×
6088
                        "be included in each path")
×
6089
        }
×
6090

6091
        addInvoiceCfg := &invoicesrpc.AddInvoiceConfig{
3✔
6092
                AddInvoice:        r.server.invoices.AddInvoice,
3✔
6093
                IsChannelActive:   r.server.htlcSwitch.HasActiveLink,
3✔
6094
                ChainParams:       r.cfg.ActiveNetParams.Params,
3✔
6095
                NodeSigner:        r.server.nodeSigner,
3✔
6096
                DefaultCLTVExpiry: defaultDelta,
3✔
6097
                ChanDB:            r.server.chanStateDB,
3✔
6098
                Graph:             r.server.graphDB,
3✔
6099
                GenInvoiceFeatures: func() *lnwire.FeatureVector {
6✔
6100
                        v := r.server.featureMgr.Get(feature.SetInvoice)
3✔
6101

3✔
6102
                        if blind {
6✔
6103
                                // If an invoice includes blinded paths, then a
3✔
6104
                                // payment address is not required since we use
3✔
6105
                                // the PathID in the final hop's encrypted data
3✔
6106
                                // as equivalent to the payment address
3✔
6107
                                v.Unset(lnwire.PaymentAddrRequired)
3✔
6108
                                v.Set(lnwire.PaymentAddrOptional)
3✔
6109

3✔
6110
                                // The invoice payer will also need to
3✔
6111
                                // understand the new BOLT 11 tagged field
3✔
6112
                                // containing the blinded path, so we switch
3✔
6113
                                // the bit to required.
3✔
6114
                                v = feature.SetBit(
3✔
6115
                                        v, lnwire.Bolt11BlindedPathsRequired,
3✔
6116
                                )
3✔
6117
                        }
3✔
6118

6119
                        return v
3✔
6120
                },
6121
                GenAmpInvoiceFeatures: func() *lnwire.FeatureVector {
3✔
6122
                        return r.server.featureMgr.Get(feature.SetInvoiceAmp)
3✔
6123
                },
3✔
6124
                GetAlias:   r.server.aliasMgr.GetPeerAlias,
6125
                BestHeight: r.server.cc.BestBlockTracker.BestHeight,
6126
                QueryBlindedRoutes: func(amt lnwire.MilliSatoshi) (
6127
                        []*route.Route, error) {
3✔
6128

3✔
6129
                        return r.server.chanRouter.FindBlindedPaths(
3✔
6130
                                r.selfNode, amt,
3✔
6131
                                r.server.defaultMC.GetProbability,
3✔
6132
                                blindingRestrictions,
3✔
6133
                        )
3✔
6134
                },
3✔
6135
        }
6136

6137
        value, err := lnrpc.UnmarshallAmt(invoice.Value, invoice.ValueMsat)
3✔
6138
        if err != nil {
3✔
6139
                return nil, err
×
6140
        }
×
6141

6142
        // Convert the passed routing hints to the required format.
6143
        routeHints, err := invoicesrpc.CreateZpay32HopHints(invoice.RouteHints)
3✔
6144
        if err != nil {
3✔
6145
                return nil, err
×
6146
        }
×
6147

6148
        var blindedPathCfg *invoicesrpc.BlindedPathConfig
3✔
6149
        if blind {
6✔
6150
                bpConfig := r.server.cfg.Routing.BlindedPaths
3✔
6151

3✔
6152
                blindedPathCfg = &invoicesrpc.BlindedPathConfig{
3✔
6153
                        RoutePolicyIncrMultiplier: bpConfig.
3✔
6154
                                PolicyIncreaseMultiplier,
3✔
6155
                        RoutePolicyDecrMultiplier: bpConfig.
3✔
6156
                                PolicyDecreaseMultiplier,
3✔
6157
                        DefaultDummyHopPolicy: &blindedpath.BlindedHopPolicy{
3✔
6158
                                CLTVExpiryDelta: uint16(defaultDelta),
3✔
6159
                                FeeRate: uint32(
3✔
6160
                                        r.server.cfg.Bitcoin.FeeRate,
3✔
6161
                                ),
3✔
6162
                                BaseFee:     r.server.cfg.Bitcoin.BaseFee,
3✔
6163
                                MinHTLCMsat: r.server.cfg.Bitcoin.MinHTLCIn,
3✔
6164

3✔
6165
                                // MaxHTLCMsat will be calculated on the fly by
3✔
6166
                                // using the introduction node's channel's
3✔
6167
                                // capacities.
3✔
6168
                                MaxHTLCMsat: 0,
3✔
6169
                        },
3✔
6170
                        MinNumPathHops: blindingRestrictions.NumHops,
3✔
6171
                }
3✔
6172
        }
3✔
6173

6174
        addInvoiceData := &invoicesrpc.AddInvoiceData{
3✔
6175
                Memo:            invoice.Memo,
3✔
6176
                Value:           value,
3✔
6177
                DescriptionHash: invoice.DescriptionHash,
3✔
6178
                Expiry:          invoice.Expiry,
3✔
6179
                FallbackAddr:    invoice.FallbackAddr,
3✔
6180
                CltvExpiry:      invoice.CltvExpiry,
3✔
6181
                Private:         invoice.Private,
3✔
6182
                RouteHints:      routeHints,
3✔
6183
                Amp:             invoice.IsAmp,
3✔
6184
                BlindedPathCfg:  blindedPathCfg,
3✔
6185
        }
3✔
6186

3✔
6187
        if invoice.RPreimage != nil {
6✔
6188
                preimage, err := lntypes.MakePreimage(invoice.RPreimage)
3✔
6189
                if err != nil {
3✔
6190
                        return nil, err
×
6191
                }
×
6192
                addInvoiceData.Preimage = &preimage
3✔
6193
        }
6194

6195
        hash, dbInvoice, err := invoicesrpc.AddInvoice(
3✔
6196
                ctx, addInvoiceCfg, addInvoiceData,
3✔
6197
        )
3✔
6198
        if err != nil {
3✔
6199
                return nil, err
×
6200
        }
×
6201

6202
        return &lnrpc.AddInvoiceResponse{
3✔
6203
                AddIndex:       dbInvoice.AddIndex,
3✔
6204
                PaymentRequest: string(dbInvoice.PaymentRequest),
3✔
6205
                RHash:          hash[:],
3✔
6206
                PaymentAddr:    dbInvoice.Terms.PaymentAddr[:],
3✔
6207
        }, nil
3✔
6208
}
6209

6210
// LookupInvoice attempts to look up an invoice according to its payment hash.
6211
// The passed payment hash *must* be exactly 32 bytes, if not an error is
6212
// returned.
6213
func (r *rpcServer) LookupInvoice(ctx context.Context,
6214
        req *lnrpc.PaymentHash) (*lnrpc.Invoice, error) {
3✔
6215

3✔
6216
        var (
3✔
6217
                payHash [32]byte
3✔
6218
                rHash   []byte
3✔
6219
                err     error
3✔
6220
        )
3✔
6221

3✔
6222
        // If the RHash as a raw string was provided, then decode that and use
3✔
6223
        // that directly. Otherwise, we use the raw bytes provided.
3✔
6224
        if req.RHashStr != "" {
6✔
6225
                rHash, err = hex.DecodeString(req.RHashStr)
3✔
6226
                if err != nil {
3✔
6227
                        return nil, err
×
6228
                }
×
6229
        } else {
3✔
6230
                rHash = req.RHash
3✔
6231
        }
3✔
6232

6233
        // Ensure that the payment hash is *exactly* 32-bytes.
6234
        if len(rHash) != 0 && len(rHash) != 32 {
3✔
6235
                return nil, fmt.Errorf("payment hash must be exactly "+
×
6236
                        "32 bytes, is instead %v", len(rHash))
×
6237
        }
×
6238
        copy(payHash[:], rHash)
3✔
6239

3✔
6240
        rpcsLog.Tracef("[lookupinvoice] searching for invoice %x", payHash[:])
3✔
6241

3✔
6242
        invoice, err := r.server.invoices.LookupInvoice(ctx, payHash)
3✔
6243
        switch {
3✔
6244
        case errors.Is(err, invoices.ErrInvoiceNotFound):
×
6245
                return nil, status.Error(codes.NotFound, err.Error())
×
6246
        case err != nil:
×
6247
                return nil, err
×
6248
        }
6249

6250
        rpcsLog.Tracef("[lookupinvoice] located invoice %v",
3✔
6251
                lnutils.SpewLogClosure(invoice))
3✔
6252

3✔
6253
        rpcInvoice, err := invoicesrpc.CreateRPCInvoice(
3✔
6254
                &invoice, r.cfg.ActiveNetParams.Params,
3✔
6255
        )
3✔
6256
        if err != nil {
3✔
6257
                return nil, err
×
6258
        }
×
6259

6260
        // Give the aux data parser a chance to format the custom data in the
6261
        // invoice HTLCs.
6262
        err = fn.MapOptionZ(
3✔
6263
                r.server.implCfg.AuxDataParser,
3✔
6264
                func(parser AuxDataParser) error {
3✔
6265
                        return parser.InlineParseCustomData(rpcInvoice)
×
6266
                },
×
6267
        )
6268
        if err != nil {
3✔
6269
                return nil, fmt.Errorf("error parsing custom data: %w",
×
6270
                        err)
×
6271
        }
×
6272

6273
        return rpcInvoice, nil
3✔
6274
}
6275

6276
// ListInvoices returns a list of all the invoices currently stored within the
6277
// database. Any active debug invoices are ignored.
6278
func (r *rpcServer) ListInvoices(ctx context.Context,
6279
        req *lnrpc.ListInvoiceRequest) (*lnrpc.ListInvoiceResponse, error) {
3✔
6280

3✔
6281
        // If the number of invoices was not specified, then we'll default to
3✔
6282
        // returning the latest 100 invoices.
3✔
6283
        if req.NumMaxInvoices == 0 {
6✔
6284
                req.NumMaxInvoices = 100
3✔
6285
        }
3✔
6286

6287
        // If both dates are set, we check that the start date is less than the
6288
        // end date, otherwise we'll get an empty result.
6289
        if req.CreationDateStart != 0 && req.CreationDateEnd != 0 {
3✔
6290
                if req.CreationDateStart >= req.CreationDateEnd {
×
6291
                        return nil, fmt.Errorf("start date(%v) must be before "+
×
6292
                                "end date(%v)", req.CreationDateStart,
×
6293
                                req.CreationDateEnd)
×
6294
                }
×
6295
        }
6296

6297
        // Next, we'll map the proto request into a format that is understood by
6298
        // the database.
6299
        q := invoices.InvoiceQuery{
3✔
6300
                IndexOffset:       req.IndexOffset,
3✔
6301
                NumMaxInvoices:    req.NumMaxInvoices,
3✔
6302
                PendingOnly:       req.PendingOnly,
3✔
6303
                Reversed:          req.Reversed,
3✔
6304
                CreationDateStart: int64(req.CreationDateStart),
3✔
6305
                CreationDateEnd:   int64(req.CreationDateEnd),
3✔
6306
        }
3✔
6307

3✔
6308
        invoiceSlice, err := r.server.invoicesDB.QueryInvoices(ctx, q)
3✔
6309
        if err != nil {
3✔
6310
                return nil, fmt.Errorf("unable to query invoices: %w", err)
×
6311
        }
×
6312

6313
        // Before returning the response, we'll need to convert each invoice
6314
        // into it's proto representation.
6315
        resp := &lnrpc.ListInvoiceResponse{
3✔
6316
                Invoices:         make([]*lnrpc.Invoice, len(invoiceSlice.Invoices)),
3✔
6317
                FirstIndexOffset: invoiceSlice.FirstIndexOffset,
3✔
6318
                LastIndexOffset:  invoiceSlice.LastIndexOffset,
3✔
6319
        }
3✔
6320
        for i, invoice := range invoiceSlice.Invoices {
6✔
6321
                invoice := invoice
3✔
6322
                resp.Invoices[i], err = invoicesrpc.CreateRPCInvoice(
3✔
6323
                        &invoice, r.cfg.ActiveNetParams.Params,
3✔
6324
                )
3✔
6325
                if err != nil {
3✔
6326
                        return nil, err
×
6327
                }
×
6328

6329
                // Give the aux data parser a chance to format the custom data
6330
                // in the invoice HTLCs.
6331
                err = fn.MapOptionZ(
3✔
6332
                        r.server.implCfg.AuxDataParser,
3✔
6333
                        func(parser AuxDataParser) error {
3✔
6334
                                return parser.InlineParseCustomData(
×
6335
                                        resp.Invoices[i],
×
6336
                                )
×
6337
                        },
×
6338
                )
6339
                if err != nil {
3✔
6340
                        return nil, fmt.Errorf("error parsing custom data: %w",
×
6341
                                err)
×
6342
                }
×
6343
        }
6344

6345
        return resp, nil
3✔
6346
}
6347

6348
// SubscribeInvoices returns a uni-directional stream (server -> client) for
6349
// notifying the client of newly added/settled invoices.
6350
func (r *rpcServer) SubscribeInvoices(req *lnrpc.InvoiceSubscription,
6351
        updateStream lnrpc.Lightning_SubscribeInvoicesServer) error {
3✔
6352

3✔
6353
        invoiceClient, err := r.server.invoices.SubscribeNotifications(
3✔
6354
                updateStream.Context(), req.AddIndex, req.SettleIndex,
3✔
6355
        )
3✔
6356
        if err != nil {
3✔
6357
                return err
×
6358
        }
×
6359
        defer invoiceClient.Cancel()
3✔
6360

3✔
6361
        for {
6✔
6362
                select {
3✔
6363
                case newInvoice := <-invoiceClient.NewInvoices:
3✔
6364
                        rpcInvoice, err := invoicesrpc.CreateRPCInvoice(
3✔
6365
                                newInvoice, r.cfg.ActiveNetParams.Params,
3✔
6366
                        )
3✔
6367
                        if err != nil {
3✔
6368
                                return err
×
6369
                        }
×
6370

6371
                        // Give the aux data parser a chance to format the
6372
                        // custom data in the invoice HTLCs.
6373
                        err = fn.MapOptionZ(
3✔
6374
                                r.server.implCfg.AuxDataParser,
3✔
6375
                                func(parser AuxDataParser) error {
3✔
6376
                                        return parser.InlineParseCustomData(
×
6377
                                                rpcInvoice,
×
6378
                                        )
×
6379
                                },
×
6380
                        )
6381
                        if err != nil {
3✔
6382
                                return fmt.Errorf("error parsing custom data: "+
×
6383
                                        "%w", err)
×
6384
                        }
×
6385

6386
                        if err := updateStream.Send(rpcInvoice); err != nil {
3✔
6387
                                return err
×
6388
                        }
×
6389

6390
                case settledInvoice := <-invoiceClient.SettledInvoices:
3✔
6391
                        rpcInvoice, err := invoicesrpc.CreateRPCInvoice(
3✔
6392
                                settledInvoice, r.cfg.ActiveNetParams.Params,
3✔
6393
                        )
3✔
6394
                        if err != nil {
3✔
6395
                                return err
×
6396
                        }
×
6397

6398
                        // Give the aux data parser a chance to format the
6399
                        // custom data in the invoice HTLCs.
6400
                        err = fn.MapOptionZ(
3✔
6401
                                r.server.implCfg.AuxDataParser,
3✔
6402
                                func(parser AuxDataParser) error {
3✔
6403
                                        return parser.InlineParseCustomData(
×
6404
                                                rpcInvoice,
×
6405
                                        )
×
6406
                                },
×
6407
                        )
6408
                        if err != nil {
3✔
6409
                                return fmt.Errorf("error parsing custom data: "+
×
6410
                                        "%w", err)
×
6411
                        }
×
6412

6413
                        if err := updateStream.Send(rpcInvoice); err != nil {
3✔
6414
                                return err
×
6415
                        }
×
6416

6417
                // The response stream's context for whatever reason has been
6418
                // closed. If context is closed by an exceeded deadline we will
6419
                // return an error.
6420
                case <-updateStream.Context().Done():
3✔
6421
                        if errors.Is(updateStream.Context().Err(), context.Canceled) {
6✔
6422
                                return nil
3✔
6423
                        }
3✔
6424
                        return updateStream.Context().Err()
×
6425

6426
                case <-r.quit:
×
6427
                        return nil
×
6428
                }
6429
        }
6430
}
6431

6432
// SubscribeTransactions creates a uni-directional stream (server -> client) in
6433
// which any newly discovered transactions relevant to the wallet are sent
6434
// over.
6435
func (r *rpcServer) SubscribeTransactions(req *lnrpc.GetTransactionsRequest,
6436
        updateStream lnrpc.Lightning_SubscribeTransactionsServer) error {
×
6437

×
6438
        txClient, err := r.server.cc.Wallet.SubscribeTransactions()
×
6439
        if err != nil {
×
6440
                return err
×
6441
        }
×
6442
        defer txClient.Cancel()
×
6443
        rpcsLog.Infof("New transaction subscription")
×
6444

×
6445
        for {
×
6446
                select {
×
6447
                case tx := <-txClient.ConfirmedTransactions():
×
6448
                        detail := lnrpc.RPCTransaction(tx)
×
6449
                        if err := updateStream.Send(detail); err != nil {
×
6450
                                return err
×
6451
                        }
×
6452

6453
                case tx := <-txClient.UnconfirmedTransactions():
×
6454
                        detail := lnrpc.RPCTransaction(tx)
×
6455
                        if err := updateStream.Send(detail); err != nil {
×
6456
                                return err
×
6457
                        }
×
6458

6459
                // The response stream's context for whatever reason has been
6460
                // closed. If context is closed by an exceeded deadline we will
6461
                // return an error.
6462
                case <-updateStream.Context().Done():
×
6463
                        rpcsLog.Infof("Canceling transaction subscription")
×
6464
                        if errors.Is(updateStream.Context().Err(), context.Canceled) {
×
6465
                                return nil
×
6466
                        }
×
6467
                        return updateStream.Context().Err()
×
6468

6469
                case <-r.quit:
×
6470
                        return nil
×
6471
                }
6472
        }
6473
}
6474

6475
// GetTransactions returns a list of describing all the known transactions
6476
// relevant to the wallet.
6477
func (r *rpcServer) GetTransactions(ctx context.Context,
6478
        req *lnrpc.GetTransactionsRequest) (*lnrpc.TransactionDetails, error) {
3✔
6479

3✔
6480
        // To remain backwards compatible with the old api, default to the
3✔
6481
        // special case end height which will return transactions from the start
3✔
6482
        // height until the chain tip, including unconfirmed transactions.
3✔
6483
        var endHeight = btcwallet.UnconfirmedHeight
3✔
6484

3✔
6485
        // If the user has provided an end height, we overwrite our default.
3✔
6486
        if req.EndHeight != 0 {
6✔
6487
                endHeight = req.EndHeight
3✔
6488
        }
3✔
6489

6490
        txns, firstIdx, lastIdx, err :=
3✔
6491
                r.server.cc.Wallet.ListTransactionDetails(
3✔
6492
                        req.StartHeight, endHeight, req.Account,
3✔
6493
                        req.IndexOffset, req.MaxTransactions,
3✔
6494
                )
3✔
6495
        if err != nil {
3✔
6496
                return nil, err
×
6497
        }
×
6498

6499
        return lnrpc.RPCTransactionDetails(txns, firstIdx, lastIdx), nil
3✔
6500
}
6501

6502
// DescribeGraph returns a description of the latest graph state from the PoV
6503
// of the node. The graph information is partitioned into two components: all
6504
// the nodes/vertexes, and all the edges that connect the vertexes themselves.
6505
// As this is a directed graph, the edges also contain the node directional
6506
// specific routing policy which includes: the time lock delta, fee
6507
// information, etc.
6508
func (r *rpcServer) DescribeGraph(ctx context.Context,
6509
        req *lnrpc.ChannelGraphRequest) (*lnrpc.ChannelGraph, error) {
3✔
6510

3✔
6511
        resp := &lnrpc.ChannelGraph{}
3✔
6512
        includeUnannounced := req.IncludeUnannounced
3✔
6513

3✔
6514
        // Check to see if the cache is already populated, if so then we can
3✔
6515
        // just return it directly.
3✔
6516
        //
3✔
6517
        // TODO(roasbeef): move this to an interceptor level feature?
3✔
6518
        graphCacheActive := r.cfg.Caches.RPCGraphCacheDuration != 0
3✔
6519
        if graphCacheActive {
6✔
6520
                r.graphCache.Lock()
3✔
6521
                defer r.graphCache.Unlock()
3✔
6522

3✔
6523
                if r.describeGraphResp != nil {
6✔
6524
                        return r.describeGraphResp, nil
3✔
6525
                }
3✔
6526
        }
6527

6528
        // Obtain the pointer to the global singleton channel graph, this will
6529
        // provide a consistent view of the graph due to bolt db's
6530
        // transactional model.
6531
        graph := r.server.graphDB
3✔
6532

3✔
6533
        // First iterate through all the known nodes (connected or unconnected
3✔
6534
        // within the graph), collating their current state into the RPC
3✔
6535
        // response.
3✔
6536
        err := graph.ForEachNode(func(_ kvdb.RTx,
3✔
6537
                node *models.LightningNode) error {
6✔
6538

3✔
6539
                lnNode := marshalNode(node)
3✔
6540

3✔
6541
                resp.Nodes = append(resp.Nodes, lnNode)
3✔
6542

3✔
6543
                return nil
3✔
6544
        })
3✔
6545
        if err != nil {
3✔
6546
                return nil, err
×
6547
        }
×
6548

6549
        // Next, for each active channel we know of within the graph, create a
6550
        // similar response which details both the edge information as well as
6551
        // the routing policies of th nodes connecting the two edges.
6552
        err = graph.ForEachChannel(func(edgeInfo *models.ChannelEdgeInfo,
3✔
6553
                c1, c2 *models.ChannelEdgePolicy) error {
6✔
6554

3✔
6555
                // Do not include unannounced channels unless specifically
3✔
6556
                // requested. Unannounced channels include both private channels as
3✔
6557
                // well as public channels whose authentication proof were not
3✔
6558
                // confirmed yet, hence were not announced.
3✔
6559
                if !includeUnannounced && edgeInfo.AuthProof == nil {
6✔
6560
                        return nil
3✔
6561
                }
3✔
6562

6563
                edge := marshalDBEdge(edgeInfo, c1, c2)
3✔
6564
                resp.Edges = append(resp.Edges, edge)
3✔
6565

3✔
6566
                return nil
3✔
6567
        })
6568
        if err != nil && !errors.Is(err, graphdb.ErrGraphNoEdgesFound) {
3✔
6569
                return nil, err
×
6570
        }
×
6571

6572
        // We still have the mutex held, so we can safely populate the cache
6573
        // now to save on GC churn for this query, but only if the cache isn't
6574
        // disabled.
6575
        if graphCacheActive {
6✔
6576
                r.describeGraphResp = resp
3✔
6577
        }
3✔
6578

6579
        return resp, nil
3✔
6580
}
6581

6582
// marshalExtraOpaqueData marshals the given tlv data. If the tlv stream is
6583
// malformed or empty, an empty map is returned. This makes the method safe to
6584
// use on unvalidated data.
6585
func marshalExtraOpaqueData(data []byte) map[uint64][]byte {
3✔
6586
        r := bytes.NewReader(data)
3✔
6587

3✔
6588
        tlvStream, err := tlv.NewStream()
3✔
6589
        if err != nil {
3✔
6590
                return nil
×
6591
        }
×
6592

6593
        // Since ExtraOpaqueData is provided by a potentially malicious peer,
6594
        // pass it into the P2P decoding variant.
6595
        parsedTypes, err := tlvStream.DecodeWithParsedTypesP2P(r)
3✔
6596
        if err != nil || len(parsedTypes) == 0 {
6✔
6597
                return nil
3✔
6598
        }
3✔
6599

6600
        records := make(map[uint64][]byte)
3✔
6601
        for k, v := range parsedTypes {
6✔
6602
                records[uint64(k)] = v
3✔
6603
        }
3✔
6604

6605
        return records
3✔
6606
}
6607

6608
// extractInboundFeeSafe tries to extract the inbound fee from the given extra
6609
// opaque data tlv block. If parsing fails, a zero inbound fee is returned. This
6610
// function is typically used on unvalidated data coming stored in the database.
6611
// There is not much we can do other than ignoring errors here.
6612
func extractInboundFeeSafe(data lnwire.ExtraOpaqueData) lnwire.Fee {
3✔
6613
        var inboundFee lnwire.Fee
3✔
6614

3✔
6615
        _, err := data.ExtractRecords(&inboundFee)
3✔
6616
        if err != nil {
3✔
6617
                // Return zero fee. Do not return the inboundFee variable
×
6618
                // because it may be undefined.
×
6619
                return lnwire.Fee{}
×
6620
        }
×
6621

6622
        return inboundFee
3✔
6623
}
6624

6625
func marshalDBEdge(edgeInfo *models.ChannelEdgeInfo,
6626
        c1, c2 *models.ChannelEdgePolicy) *lnrpc.ChannelEdge {
3✔
6627

3✔
6628
        // Make sure the policies match the node they belong to. c1 should point
3✔
6629
        // to the policy for NodeKey1, and c2 for NodeKey2.
3✔
6630
        if c1 != nil && c1.ChannelFlags&lnwire.ChanUpdateDirection == 1 ||
3✔
6631
                c2 != nil && c2.ChannelFlags&lnwire.ChanUpdateDirection == 0 {
3✔
6632

×
6633
                c2, c1 = c1, c2
×
6634
        }
×
6635

6636
        var lastUpdate int64
3✔
6637
        if c1 != nil {
6✔
6638
                lastUpdate = c1.LastUpdate.Unix()
3✔
6639
        }
3✔
6640
        if c2 != nil && c2.LastUpdate.Unix() > lastUpdate {
6✔
6641
                lastUpdate = c2.LastUpdate.Unix()
3✔
6642
        }
3✔
6643

6644
        customRecords := marshalExtraOpaqueData(edgeInfo.ExtraOpaqueData)
3✔
6645

3✔
6646
        edge := &lnrpc.ChannelEdge{
3✔
6647
                ChannelId: edgeInfo.ChannelID,
3✔
6648
                ChanPoint: edgeInfo.ChannelPoint.String(),
3✔
6649
                // TODO(roasbeef): update should be on edge info itself
3✔
6650
                LastUpdate:    uint32(lastUpdate),
3✔
6651
                Node1Pub:      hex.EncodeToString(edgeInfo.NodeKey1Bytes[:]),
3✔
6652
                Node2Pub:      hex.EncodeToString(edgeInfo.NodeKey2Bytes[:]),
3✔
6653
                Capacity:      int64(edgeInfo.Capacity),
3✔
6654
                CustomRecords: customRecords,
3✔
6655
        }
3✔
6656

3✔
6657
        if c1 != nil {
6✔
6658
                edge.Node1Policy = marshalDBRoutingPolicy(c1)
3✔
6659
        }
3✔
6660

6661
        if c2 != nil {
6✔
6662
                edge.Node2Policy = marshalDBRoutingPolicy(c2)
3✔
6663
        }
3✔
6664

6665
        return edge
3✔
6666
}
6667

6668
func marshalDBRoutingPolicy(
6669
        policy *models.ChannelEdgePolicy) *lnrpc.RoutingPolicy {
3✔
6670

3✔
6671
        disabled := policy.ChannelFlags&lnwire.ChanUpdateDisabled != 0
3✔
6672

3✔
6673
        customRecords := marshalExtraOpaqueData(policy.ExtraOpaqueData)
3✔
6674
        inboundFee := extractInboundFeeSafe(policy.ExtraOpaqueData)
3✔
6675

3✔
6676
        return &lnrpc.RoutingPolicy{
3✔
6677
                TimeLockDelta:    uint32(policy.TimeLockDelta),
3✔
6678
                MinHtlc:          int64(policy.MinHTLC),
3✔
6679
                MaxHtlcMsat:      uint64(policy.MaxHTLC),
3✔
6680
                FeeBaseMsat:      int64(policy.FeeBaseMSat),
3✔
6681
                FeeRateMilliMsat: int64(policy.FeeProportionalMillionths),
3✔
6682
                Disabled:         disabled,
3✔
6683
                LastUpdate:       uint32(policy.LastUpdate.Unix()),
3✔
6684
                CustomRecords:    customRecords,
3✔
6685

3✔
6686
                InboundFeeBaseMsat:      inboundFee.BaseFee,
3✔
6687
                InboundFeeRateMilliMsat: inboundFee.FeeRate,
3✔
6688
        }
3✔
6689
}
3✔
6690

6691
// GetNodeMetrics returns all available node metrics calculated from the
6692
// current channel graph.
6693
func (r *rpcServer) GetNodeMetrics(ctx context.Context,
6694
        req *lnrpc.NodeMetricsRequest) (*lnrpc.NodeMetricsResponse, error) {
×
6695

×
6696
        // Get requested metric types.
×
6697
        getCentrality := false
×
6698
        for _, t := range req.Types {
×
6699
                if t == lnrpc.NodeMetricType_BETWEENNESS_CENTRALITY {
×
6700
                        getCentrality = true
×
6701
                }
×
6702
        }
6703

6704
        // Only centrality can be requested for now.
6705
        if !getCentrality {
×
6706
                return nil, nil
×
6707
        }
×
6708

6709
        resp := &lnrpc.NodeMetricsResponse{
×
6710
                BetweennessCentrality: make(map[string]*lnrpc.FloatMetric),
×
6711
        }
×
6712

×
6713
        // Obtain the pointer to the global singleton channel graph, this will
×
6714
        // provide a consistent view of the graph due to bolt db's
×
6715
        // transactional model.
×
6716
        graph := r.server.graphDB
×
6717

×
6718
        // Calculate betweenness centrality if requested. Note that depending on the
×
6719
        // graph size, this may take up to a few minutes.
×
6720
        channelGraph := autopilot.ChannelGraphFromDatabase(graph)
×
6721
        centralityMetric, err := autopilot.NewBetweennessCentralityMetric(
×
6722
                runtime.NumCPU(),
×
6723
        )
×
6724
        if err != nil {
×
6725
                return nil, err
×
6726
        }
×
6727
        if err := centralityMetric.Refresh(channelGraph); err != nil {
×
6728
                return nil, err
×
6729
        }
×
6730

6731
        // Fill normalized and non normalized centrality.
6732
        centrality := centralityMetric.GetMetric(true)
×
6733
        for nodeID, val := range centrality {
×
6734
                resp.BetweennessCentrality[hex.EncodeToString(nodeID[:])] =
×
6735
                        &lnrpc.FloatMetric{
×
6736
                                NormalizedValue: val,
×
6737
                        }
×
6738
        }
×
6739

6740
        centrality = centralityMetric.GetMetric(false)
×
6741
        for nodeID, val := range centrality {
×
6742
                resp.BetweennessCentrality[hex.EncodeToString(nodeID[:])].Value = val
×
6743
        }
×
6744

6745
        return resp, nil
×
6746
}
6747

6748
// GetChanInfo returns the latest authenticated network announcement for the
6749
// given channel identified by either its channel ID or a channel outpoint. Both
6750
// uniquely identify the location of transaction's funding output within the
6751
// blockchain. The former is an 8-byte integer, while the latter is a string
6752
// formatted as funding_txid:output_index.
6753
func (r *rpcServer) GetChanInfo(_ context.Context,
6754
        in *lnrpc.ChanInfoRequest) (*lnrpc.ChannelEdge, error) {
3✔
6755

3✔
6756
        graph := r.server.graphDB
3✔
6757

3✔
6758
        var (
3✔
6759
                edgeInfo     *models.ChannelEdgeInfo
3✔
6760
                edge1, edge2 *models.ChannelEdgePolicy
3✔
6761
                err          error
3✔
6762
        )
3✔
6763

3✔
6764
        switch {
3✔
6765
        case in.ChanId != 0:
3✔
6766
                edgeInfo, edge1, edge2, err = graph.FetchChannelEdgesByID(
3✔
6767
                        in.ChanId,
3✔
6768
                )
3✔
6769

6770
        case in.ChanPoint != "":
3✔
6771
                var chanPoint *wire.OutPoint
3✔
6772
                chanPoint, err = wire.NewOutPointFromString(in.ChanPoint)
3✔
6773
                if err != nil {
3✔
6774
                        return nil, err
×
6775
                }
×
6776
                edgeInfo, edge1, edge2, err = graph.FetchChannelEdgesByOutpoint(
3✔
6777
                        chanPoint,
3✔
6778
                )
3✔
6779

6780
        default:
×
6781
                return nil, fmt.Errorf("specify either chan_id or chan_point")
×
6782
        }
6783
        if err != nil {
6✔
6784
                return nil, err
3✔
6785
        }
3✔
6786

6787
        // Convert the database's edge format into the network/RPC edge format
6788
        // which couples the edge itself along with the directional node
6789
        // routing policies of each node involved within the channel.
6790
        channelEdge := marshalDBEdge(edgeInfo, edge1, edge2)
3✔
6791

3✔
6792
        return channelEdge, nil
3✔
6793
}
6794

6795
// GetNodeInfo returns the latest advertised and aggregate authenticated
6796
// channel information for the specified node identified by its public key.
6797
func (r *rpcServer) GetNodeInfo(ctx context.Context,
6798
        in *lnrpc.NodeInfoRequest) (*lnrpc.NodeInfo, error) {
×
6799

×
6800
        graph := r.server.graphDB
×
6801

×
6802
        // First, parse the hex-encoded public key into a full in-memory public
×
6803
        // key object we can work with for querying.
×
6804
        pubKey, err := route.NewVertexFromStr(in.PubKey)
×
6805
        if err != nil {
×
6806
                return nil, err
×
6807
        }
×
6808

6809
        // With the public key decoded, attempt to fetch the node corresponding
6810
        // to this public key. If the node cannot be found, then an error will
6811
        // be returned.
6812
        node, err := graph.FetchLightningNode(pubKey)
×
6813
        switch {
×
6814
        case errors.Is(err, graphdb.ErrGraphNodeNotFound):
×
6815
                return nil, status.Error(codes.NotFound, err.Error())
×
6816
        case err != nil:
×
6817
                return nil, err
×
6818
        }
6819

6820
        // With the node obtained, we'll now iterate through all its out going
6821
        // edges to gather some basic statistics about its out going channels.
6822
        var (
×
6823
                numChannels   uint32
×
6824
                totalCapacity btcutil.Amount
×
6825
                channels      []*lnrpc.ChannelEdge
×
6826
        )
×
6827

×
6828
        err = graph.ForEachNodeChannel(node.PubKeyBytes,
×
6829
                func(_ kvdb.RTx, edge *models.ChannelEdgeInfo,
×
6830
                        c1, c2 *models.ChannelEdgePolicy) error {
×
6831

×
6832
                        numChannels++
×
6833
                        totalCapacity += edge.Capacity
×
6834

×
6835
                        // Only populate the node's channels if the user
×
6836
                        // requested them.
×
6837
                        if in.IncludeChannels {
×
6838
                                // Do not include unannounced channels - private
×
6839
                                // channels or public channels whose
×
6840
                                // authentication proof were not confirmed yet.
×
6841
                                if edge.AuthProof == nil {
×
6842
                                        return nil
×
6843
                                }
×
6844

6845
                                // Convert the database's edge format into the
6846
                                // network/RPC edge format.
6847
                                channelEdge := marshalDBEdge(edge, c1, c2)
×
6848
                                channels = append(channels, channelEdge)
×
6849
                        }
6850

6851
                        return nil
×
6852
                },
6853
        )
6854
        if err != nil {
×
6855
                return nil, err
×
6856
        }
×
6857

6858
        return &lnrpc.NodeInfo{
×
6859
                Node:          marshalNode(node),
×
6860
                NumChannels:   numChannels,
×
6861
                TotalCapacity: int64(totalCapacity),
×
6862
                Channels:      channels,
×
6863
        }, nil
×
6864
}
6865

6866
func marshalNode(node *models.LightningNode) *lnrpc.LightningNode {
3✔
6867
        nodeAddrs := make([]*lnrpc.NodeAddress, len(node.Addresses))
3✔
6868
        for i, addr := range node.Addresses {
6✔
6869
                nodeAddr := &lnrpc.NodeAddress{
3✔
6870
                        Network: addr.Network(),
3✔
6871
                        Addr:    addr.String(),
3✔
6872
                }
3✔
6873
                nodeAddrs[i] = nodeAddr
3✔
6874
        }
3✔
6875

6876
        features := invoicesrpc.CreateRPCFeatures(node.Features)
3✔
6877

3✔
6878
        customRecords := marshalExtraOpaqueData(node.ExtraOpaqueData)
3✔
6879

3✔
6880
        return &lnrpc.LightningNode{
3✔
6881
                LastUpdate:    uint32(node.LastUpdate.Unix()),
3✔
6882
                PubKey:        hex.EncodeToString(node.PubKeyBytes[:]),
3✔
6883
                Addresses:     nodeAddrs,
3✔
6884
                Alias:         node.Alias,
3✔
6885
                Color:         graph.EncodeHexColor(node.Color),
3✔
6886
                Features:      features,
3✔
6887
                CustomRecords: customRecords,
3✔
6888
        }
3✔
6889
}
6890

6891
// QueryRoutes attempts to query the daemons' Channel Router for a possible
6892
// route to a target destination capable of carrying a specific amount of
6893
// satoshis within the route's flow. The returned route contains the full
6894
// details required to craft and send an HTLC, also including the necessary
6895
// information that should be present within the Sphinx packet encapsulated
6896
// within the HTLC.
6897
//
6898
// TODO(roasbeef): should return a slice of routes in reality
6899
//   - create separate PR to send based on well formatted route
6900
func (r *rpcServer) QueryRoutes(ctx context.Context,
6901
        in *lnrpc.QueryRoutesRequest) (*lnrpc.QueryRoutesResponse, error) {
3✔
6902

3✔
6903
        return r.routerBackend.QueryRoutes(ctx, in)
3✔
6904
}
3✔
6905

6906
// GetNetworkInfo returns some basic stats about the known channel graph from
6907
// the PoV of the node.
6908
func (r *rpcServer) GetNetworkInfo(ctx context.Context,
6909
        _ *lnrpc.NetworkInfoRequest) (*lnrpc.NetworkInfo, error) {
×
6910

×
6911
        graph := r.server.graphDB
×
6912

×
6913
        var (
×
6914
                numNodes             uint32
×
6915
                numChannels          uint32
×
6916
                maxChanOut           uint32
×
6917
                totalNetworkCapacity btcutil.Amount
×
6918
                minChannelSize       btcutil.Amount = math.MaxInt64
×
6919
                maxChannelSize       btcutil.Amount
×
6920
                medianChanSize       btcutil.Amount
×
6921
        )
×
6922

×
6923
        // We'll use this map to de-duplicate channels during our traversal.
×
6924
        // This is needed since channels are directional, so there will be two
×
6925
        // edges for each channel within the graph.
×
6926
        seenChans := make(map[uint64]struct{})
×
6927

×
6928
        // We also keep a list of all encountered capacities, in order to
×
6929
        // calculate the median channel size.
×
6930
        var allChans []btcutil.Amount
×
6931

×
6932
        // We'll run through all the known nodes in the within our view of the
×
6933
        // network, tallying up the total number of nodes, and also gathering
×
6934
        // each node so we can measure the graph diameter and degree stats
×
6935
        // below.
×
6936
        err := graph.ForEachNodeCached(func(node route.Vertex,
×
6937
                edges map[uint64]*graphdb.DirectedChannel) error {
×
6938

×
6939
                // Increment the total number of nodes with each iteration.
×
6940
                numNodes++
×
6941

×
6942
                // For each channel we'll compute the out degree of each node,
×
6943
                // and also update our running tallies of the min/max channel
×
6944
                // capacity, as well as the total channel capacity. We pass
×
6945
                // through the db transaction from the outer view so we can
×
6946
                // re-use it within this inner view.
×
6947
                var outDegree uint32
×
6948
                for _, edge := range edges {
×
6949
                        // Bump up the out degree for this node for each
×
6950
                        // channel encountered.
×
6951
                        outDegree++
×
6952

×
6953
                        // If we've already seen this channel, then we'll
×
6954
                        // return early to ensure that we don't double-count
×
6955
                        // stats.
×
6956
                        if _, ok := seenChans[edge.ChannelID]; ok {
×
6957
                                return nil
×
6958
                        }
×
6959

6960
                        // Compare the capacity of this channel against the
6961
                        // running min/max to see if we should update the
6962
                        // extrema.
6963
                        chanCapacity := edge.Capacity
×
6964
                        if chanCapacity < minChannelSize {
×
6965
                                minChannelSize = chanCapacity
×
6966
                        }
×
6967
                        if chanCapacity > maxChannelSize {
×
6968
                                maxChannelSize = chanCapacity
×
6969
                        }
×
6970

6971
                        // Accumulate the total capacity of this channel to the
6972
                        // network wide-capacity.
6973
                        totalNetworkCapacity += chanCapacity
×
6974

×
6975
                        numChannels++
×
6976

×
6977
                        seenChans[edge.ChannelID] = struct{}{}
×
6978
                        allChans = append(allChans, edge.Capacity)
×
6979
                }
6980

6981
                // Finally, if the out degree of this node is greater than what
6982
                // we've seen so far, update the maxChanOut variable.
6983
                if outDegree > maxChanOut {
×
6984
                        maxChanOut = outDegree
×
6985
                }
×
6986

6987
                return nil
×
6988
        })
6989
        if err != nil {
×
6990
                return nil, err
×
6991
        }
×
6992

6993
        // Query the graph for the current number of zombie channels.
6994
        numZombies, err := graph.NumZombies()
×
6995
        if err != nil {
×
6996
                return nil, err
×
6997
        }
×
6998

6999
        // Find the median.
7000
        medianChanSize = autopilot.Median(allChans)
×
7001

×
7002
        // If we don't have any channels, then reset the minChannelSize to zero
×
7003
        // to avoid outputting NaN in encoded JSON.
×
7004
        if numChannels == 0 {
×
7005
                minChannelSize = 0
×
7006
        }
×
7007

7008
        // Graph diameter.
7009
        channelGraph := autopilot.ChannelGraphFromCachedDatabase(graph)
×
7010
        simpleGraph, err := autopilot.NewSimpleGraph(channelGraph)
×
7011
        if err != nil {
×
7012
                return nil, err
×
7013
        }
×
7014
        start := time.Now()
×
7015
        diameter := simpleGraph.DiameterRadialCutoff()
×
7016
        rpcsLog.Infof("elapsed time for diameter (%d) calculation: %v", diameter,
×
7017
                time.Since(start))
×
7018

×
7019
        // TODO(roasbeef): also add oldest channel?
×
7020
        netInfo := &lnrpc.NetworkInfo{
×
7021
                GraphDiameter:        diameter,
×
7022
                MaxOutDegree:         maxChanOut,
×
7023
                AvgOutDegree:         float64(2*numChannels) / float64(numNodes),
×
7024
                NumNodes:             numNodes,
×
7025
                NumChannels:          numChannels,
×
7026
                TotalNetworkCapacity: int64(totalNetworkCapacity),
×
7027
                AvgChannelSize:       float64(totalNetworkCapacity) / float64(numChannels),
×
7028

×
7029
                MinChannelSize:       int64(minChannelSize),
×
7030
                MaxChannelSize:       int64(maxChannelSize),
×
7031
                MedianChannelSizeSat: int64(medianChanSize),
×
7032
                NumZombieChans:       numZombies,
×
7033
        }
×
7034

×
7035
        // Similarly, if we don't have any channels, then we'll also set the
×
7036
        // average channel size to zero in order to avoid weird JSON encoding
×
7037
        // outputs.
×
7038
        if numChannels == 0 {
×
7039
                netInfo.AvgChannelSize = 0
×
7040
        }
×
7041

7042
        return netInfo, nil
×
7043
}
7044

7045
// StopDaemon will send a shutdown request to the interrupt handler, triggering
7046
// a graceful shutdown of the daemon.
7047
func (r *rpcServer) StopDaemon(_ context.Context,
7048
        _ *lnrpc.StopRequest) (*lnrpc.StopResponse, error) {
3✔
7049

3✔
7050
        // Before we even consider a shutdown, are we currently in recovery
3✔
7051
        // mode? We don't want to allow shutting down during recovery because
3✔
7052
        // that would mean the user would have to manually continue the rescan
3✔
7053
        // process next time by using `lncli unlock --recovery_window X`
3✔
7054
        // otherwise some funds wouldn't be picked up.
3✔
7055
        isRecoveryMode, progress, err := r.server.cc.Wallet.GetRecoveryInfo()
3✔
7056
        if err != nil {
3✔
7057
                return nil, fmt.Errorf("unable to get wallet recovery info: %w",
×
7058
                        err)
×
7059
        }
×
7060
        if isRecoveryMode && progress < 1 {
3✔
7061
                return nil, fmt.Errorf("wallet recovery in progress, cannot " +
×
7062
                        "shut down, please wait until rescan finishes")
×
7063
        }
×
7064

7065
        r.interceptor.RequestShutdown()
3✔
7066

3✔
7067
        return &lnrpc.StopResponse{
3✔
7068
                Status: "shutdown initiated, check logs for progress",
3✔
7069
        }, nil
3✔
7070
}
7071

7072
// SubscribeChannelGraph launches a streaming RPC that allows the caller to
7073
// receive notifications upon any changes the channel graph topology from the
7074
// review of the responding node. Events notified include: new nodes coming
7075
// online, nodes updating their authenticated attributes, new channels being
7076
// advertised, updates in the routing policy for a directional channel edge,
7077
// and finally when prior channels are closed on-chain.
7078
func (r *rpcServer) SubscribeChannelGraph(req *lnrpc.GraphTopologySubscription,
7079
        updateStream lnrpc.Lightning_SubscribeChannelGraphServer) error {
3✔
7080

3✔
7081
        // First, we start by subscribing to a new intent to receive
3✔
7082
        // notifications from the channel router.
3✔
7083
        client, err := r.server.graphBuilder.SubscribeTopology()
3✔
7084
        if err != nil {
3✔
7085
                return err
×
7086
        }
×
7087

7088
        // Ensure that the resources for the topology update client is cleaned
7089
        // up once either the server, or client exists.
7090
        defer client.Cancel()
3✔
7091

3✔
7092
        for {
6✔
7093
                select {
3✔
7094

7095
                // A new update has been sent by the channel router, we'll
7096
                // marshal it into the form expected by the gRPC client, then
7097
                // send it off.
7098
                case topChange, ok := <-client.TopologyChanges:
3✔
7099
                        // If the second value from the channel read is nil,
3✔
7100
                        // then this means that the channel router is exiting
3✔
7101
                        // or the notification client was canceled. So we'll
3✔
7102
                        // exit early.
3✔
7103
                        if !ok {
3✔
7104
                                return errors.New("server shutting down")
×
7105
                        }
×
7106

7107
                        // Convert the struct from the channel router into the
7108
                        // form expected by the gRPC service then send it off
7109
                        // to the client.
7110
                        graphUpdate := marshallTopologyChange(topChange)
3✔
7111
                        if err := updateStream.Send(graphUpdate); err != nil {
3✔
7112
                                return err
×
7113
                        }
×
7114

7115
                // The response stream's context for whatever reason has been
7116
                // closed. If context is closed by an exceeded deadline
7117
                // we will return an error.
7118
                case <-updateStream.Context().Done():
3✔
7119
                        if errors.Is(updateStream.Context().Err(), context.Canceled) {
6✔
7120
                                return nil
3✔
7121
                        }
3✔
7122
                        return updateStream.Context().Err()
×
7123

7124
                // The server is quitting, so we'll exit immediately. Returning
7125
                // nil will close the clients read end of the stream.
7126
                case <-r.quit:
×
7127
                        return nil
×
7128
                }
7129
        }
7130
}
7131

7132
// marshallTopologyChange performs a mapping from the topology change struct
7133
// returned by the router to the form of notifications expected by the current
7134
// gRPC service.
7135
func marshallTopologyChange(
7136
        topChange *graph.TopologyChange) *lnrpc.GraphTopologyUpdate {
3✔
7137

3✔
7138
        // encodeKey is a simple helper function that converts a live public
3✔
7139
        // key into a hex-encoded version of the compressed serialization for
3✔
7140
        // the public key.
3✔
7141
        encodeKey := func(k *btcec.PublicKey) string {
6✔
7142
                return hex.EncodeToString(k.SerializeCompressed())
3✔
7143
        }
3✔
7144

7145
        nodeUpdates := make([]*lnrpc.NodeUpdate, len(topChange.NodeUpdates))
3✔
7146
        for i, nodeUpdate := range topChange.NodeUpdates {
6✔
7147
                nodeAddrs := make(
3✔
7148
                        []*lnrpc.NodeAddress, 0, len(nodeUpdate.Addresses),
3✔
7149
                )
3✔
7150
                for _, addr := range nodeUpdate.Addresses {
6✔
7151
                        nodeAddr := &lnrpc.NodeAddress{
3✔
7152
                                Network: addr.Network(),
3✔
7153
                                Addr:    addr.String(),
3✔
7154
                        }
3✔
7155
                        nodeAddrs = append(nodeAddrs, nodeAddr)
3✔
7156
                }
3✔
7157

7158
                addrs := make([]string, len(nodeUpdate.Addresses))
3✔
7159
                for i, addr := range nodeUpdate.Addresses {
6✔
7160
                        addrs[i] = addr.String()
3✔
7161
                }
3✔
7162

7163
                nodeUpdates[i] = &lnrpc.NodeUpdate{
3✔
7164
                        Addresses:     addrs,
3✔
7165
                        NodeAddresses: nodeAddrs,
3✔
7166
                        IdentityKey:   encodeKey(nodeUpdate.IdentityKey),
3✔
7167
                        Alias:         nodeUpdate.Alias,
3✔
7168
                        Color:         nodeUpdate.Color,
3✔
7169
                        Features: invoicesrpc.CreateRPCFeatures(
3✔
7170
                                nodeUpdate.Features,
3✔
7171
                        ),
3✔
7172
                }
3✔
7173
        }
7174

7175
        channelUpdates := make([]*lnrpc.ChannelEdgeUpdate, len(topChange.ChannelEdgeUpdates))
3✔
7176
        for i, channelUpdate := range topChange.ChannelEdgeUpdates {
6✔
7177

3✔
7178
                customRecords := marshalExtraOpaqueData(
3✔
7179
                        channelUpdate.ExtraOpaqueData,
3✔
7180
                )
3✔
7181
                inboundFee := extractInboundFeeSafe(
3✔
7182
                        channelUpdate.ExtraOpaqueData,
3✔
7183
                )
3✔
7184

3✔
7185
                channelUpdates[i] = &lnrpc.ChannelEdgeUpdate{
3✔
7186
                        ChanId: channelUpdate.ChanID,
3✔
7187
                        ChanPoint: &lnrpc.ChannelPoint{
3✔
7188
                                FundingTxid: &lnrpc.ChannelPoint_FundingTxidBytes{
3✔
7189
                                        FundingTxidBytes: channelUpdate.ChanPoint.Hash[:],
3✔
7190
                                },
3✔
7191
                                OutputIndex: channelUpdate.ChanPoint.Index,
3✔
7192
                        },
3✔
7193
                        Capacity: int64(channelUpdate.Capacity),
3✔
7194
                        RoutingPolicy: &lnrpc.RoutingPolicy{
3✔
7195
                                TimeLockDelta: uint32(
3✔
7196
                                        channelUpdate.TimeLockDelta,
3✔
7197
                                ),
3✔
7198
                                MinHtlc: int64(
3✔
7199
                                        channelUpdate.MinHTLC,
3✔
7200
                                ),
3✔
7201
                                MaxHtlcMsat: uint64(
3✔
7202
                                        channelUpdate.MaxHTLC,
3✔
7203
                                ),
3✔
7204
                                FeeBaseMsat: int64(
3✔
7205
                                        channelUpdate.BaseFee,
3✔
7206
                                ),
3✔
7207
                                FeeRateMilliMsat: int64(
3✔
7208
                                        channelUpdate.FeeRate,
3✔
7209
                                ),
3✔
7210
                                Disabled:                channelUpdate.Disabled,
3✔
7211
                                InboundFeeBaseMsat:      inboundFee.BaseFee,
3✔
7212
                                InboundFeeRateMilliMsat: inboundFee.FeeRate,
3✔
7213
                                CustomRecords:           customRecords,
3✔
7214
                        },
3✔
7215
                        AdvertisingNode: encodeKey(channelUpdate.AdvertisingNode),
3✔
7216
                        ConnectingNode:  encodeKey(channelUpdate.ConnectingNode),
3✔
7217
                }
3✔
7218
        }
3✔
7219

7220
        closedChans := make([]*lnrpc.ClosedChannelUpdate, len(topChange.ClosedChannels))
3✔
7221
        for i, closedChan := range topChange.ClosedChannels {
6✔
7222
                closedChans[i] = &lnrpc.ClosedChannelUpdate{
3✔
7223
                        ChanId:       closedChan.ChanID,
3✔
7224
                        Capacity:     int64(closedChan.Capacity),
3✔
7225
                        ClosedHeight: closedChan.ClosedHeight,
3✔
7226
                        ChanPoint: &lnrpc.ChannelPoint{
3✔
7227
                                FundingTxid: &lnrpc.ChannelPoint_FundingTxidBytes{
3✔
7228
                                        FundingTxidBytes: closedChan.ChanPoint.Hash[:],
3✔
7229
                                },
3✔
7230
                                OutputIndex: closedChan.ChanPoint.Index,
3✔
7231
                        },
3✔
7232
                }
3✔
7233
        }
3✔
7234

7235
        return &lnrpc.GraphTopologyUpdate{
3✔
7236
                NodeUpdates:    nodeUpdates,
3✔
7237
                ChannelUpdates: channelUpdates,
3✔
7238
                ClosedChans:    closedChans,
3✔
7239
        }
3✔
7240
}
7241

7242
// ListPayments returns a list of outgoing payments determined by a paginated
7243
// database query.
7244
func (r *rpcServer) ListPayments(ctx context.Context,
7245
        req *lnrpc.ListPaymentsRequest) (*lnrpc.ListPaymentsResponse, error) {
3✔
7246

3✔
7247
        // If both dates are set, we check that the start date is less than the
3✔
7248
        // end date, otherwise we'll get an empty result.
3✔
7249
        if req.CreationDateStart != 0 && req.CreationDateEnd != 0 {
3✔
7250
                if req.CreationDateStart >= req.CreationDateEnd {
×
7251
                        return nil, fmt.Errorf("start date(%v) must be before "+
×
7252
                                "end date(%v)", req.CreationDateStart,
×
7253
                                req.CreationDateEnd)
×
7254
                }
×
7255
        }
7256

7257
        query := channeldb.PaymentsQuery{
3✔
7258
                IndexOffset:       req.IndexOffset,
3✔
7259
                MaxPayments:       req.MaxPayments,
3✔
7260
                Reversed:          req.Reversed,
3✔
7261
                IncludeIncomplete: req.IncludeIncomplete,
3✔
7262
                CountTotal:        req.CountTotalPayments,
3✔
7263
                CreationDateStart: int64(req.CreationDateStart),
3✔
7264
                CreationDateEnd:   int64(req.CreationDateEnd),
3✔
7265
        }
3✔
7266

3✔
7267
        // If the maximum number of payments wasn't specified, then we'll
3✔
7268
        // default to return the maximal number of payments representable.
3✔
7269
        if req.MaxPayments == 0 {
6✔
7270
                query.MaxPayments = math.MaxUint64
3✔
7271
        }
3✔
7272

7273
        paymentsQuerySlice, err := r.server.miscDB.QueryPayments(query)
3✔
7274
        if err != nil {
3✔
7275
                return nil, err
×
7276
        }
×
7277

7278
        paymentsResp := &lnrpc.ListPaymentsResponse{
3✔
7279
                LastIndexOffset:  paymentsQuerySlice.LastIndexOffset,
3✔
7280
                FirstIndexOffset: paymentsQuerySlice.FirstIndexOffset,
3✔
7281
                TotalNumPayments: paymentsQuerySlice.TotalCount,
3✔
7282
        }
3✔
7283

3✔
7284
        for _, payment := range paymentsQuerySlice.Payments {
6✔
7285
                payment := payment
3✔
7286

3✔
7287
                rpcPayment, err := r.routerBackend.MarshallPayment(payment)
3✔
7288
                if err != nil {
3✔
7289
                        return nil, err
×
7290
                }
×
7291

7292
                paymentsResp.Payments = append(
3✔
7293
                        paymentsResp.Payments, rpcPayment,
3✔
7294
                )
3✔
7295
        }
7296

7297
        return paymentsResp, nil
3✔
7298
}
7299

7300
// DeletePayment deletes a payment from the DB given its payment hash. If
7301
// failedHtlcsOnly is set, only failed HTLC attempts of the payment will be
7302
// deleted.
7303
func (r *rpcServer) DeletePayment(ctx context.Context,
7304
        req *lnrpc.DeletePaymentRequest) (
7305
        *lnrpc.DeletePaymentResponse, error) {
×
7306

×
7307
        hash, err := lntypes.MakeHash(req.PaymentHash)
×
7308
        if err != nil {
×
7309
                return nil, err
×
7310
        }
×
7311

7312
        rpcsLog.Infof("[DeletePayment] payment_identifier=%v, "+
×
7313
                "failed_htlcs_only=%v", hash, req.FailedHtlcsOnly)
×
7314

×
7315
        err = r.server.miscDB.DeletePayment(hash, req.FailedHtlcsOnly)
×
7316
        if err != nil {
×
7317
                return nil, err
×
7318
        }
×
7319

7320
        return &lnrpc.DeletePaymentResponse{
×
7321
                Status: "payment deleted",
×
7322
        }, nil
×
7323
}
7324

7325
// DeleteAllPayments deletes all outgoing payments from DB.
7326
func (r *rpcServer) DeleteAllPayments(ctx context.Context,
7327
        req *lnrpc.DeleteAllPaymentsRequest) (
7328
        *lnrpc.DeleteAllPaymentsResponse, error) {
3✔
7329

3✔
7330
        switch {
3✔
7331
        // Since this is a destructive operation, at least one of the options
7332
        // must be set to true.
7333
        case !req.AllPayments && !req.FailedPaymentsOnly &&
7334
                !req.FailedHtlcsOnly:
×
7335

×
7336
                return nil, fmt.Errorf("at least one of the options " +
×
7337
                        "`all_payments`, `failed_payments_only`, or " +
×
7338
                        "`failed_htlcs_only` must be set to true")
×
7339

7340
        // `all_payments` cannot be true with `failed_payments_only` or
7341
        // `failed_htlcs_only`. `all_payments` includes all records, making
7342
        // these options contradictory.
7343
        case req.AllPayments &&
7344
                (req.FailedPaymentsOnly || req.FailedHtlcsOnly):
×
7345

×
7346
                return nil, fmt.Errorf("`all_payments` cannot be set to true " +
×
7347
                        "while either `failed_payments_only` or " +
×
7348
                        "`failed_htlcs_only` is also set to true")
×
7349
        }
7350

7351
        rpcsLog.Infof("[DeleteAllPayments] failed_payments_only=%v, "+
3✔
7352
                "failed_htlcs_only=%v", req.FailedPaymentsOnly,
3✔
7353
                req.FailedHtlcsOnly)
3✔
7354

3✔
7355
        numDeletedPayments, err := r.server.miscDB.DeletePayments(
3✔
7356
                req.FailedPaymentsOnly, req.FailedHtlcsOnly,
3✔
7357
        )
3✔
7358
        if err != nil {
3✔
7359
                return nil, err
×
7360
        }
×
7361

7362
        return &lnrpc.DeleteAllPaymentsResponse{
3✔
7363
                Status: fmt.Sprintf("%v payments deleted, failed_htlcs_only=%v",
3✔
7364
                        numDeletedPayments, req.FailedHtlcsOnly),
3✔
7365
        }, nil
3✔
7366
}
7367

7368
// DebugLevel allows a caller to programmatically set the logging verbosity of
7369
// lnd. The logging can be targeted according to a coarse daemon-wide logging
7370
// level, or in a granular fashion to specify the logging for a target
7371
// sub-system.
7372
func (r *rpcServer) DebugLevel(ctx context.Context,
7373
        req *lnrpc.DebugLevelRequest) (*lnrpc.DebugLevelResponse, error) {
×
7374

×
7375
        // If show is set, then we simply print out the list of available
×
7376
        // sub-systems.
×
7377
        if req.Show {
×
7378
                return &lnrpc.DebugLevelResponse{
×
7379
                        SubSystems: strings.Join(
×
7380
                                r.cfg.SubLogMgr.SupportedSubsystems(), " ",
×
7381
                        ),
×
7382
                }, nil
×
7383
        }
×
7384

7385
        rpcsLog.Infof("[debuglevel] changing debug level to: %v", req.LevelSpec)
×
7386

×
7387
        // Otherwise, we'll attempt to set the logging level using the
×
7388
        // specified level spec.
×
7389
        err := build.ParseAndSetDebugLevels(req.LevelSpec, r.cfg.SubLogMgr)
×
7390
        if err != nil {
×
7391
                return nil, err
×
7392
        }
×
7393

7394
        subLoggers := r.cfg.SubLogMgr.SubLoggers()
×
7395
        // Sort alphabetically by subsystem name.
×
7396
        var tags []string
×
7397
        for t := range subLoggers {
×
7398
                tags = append(tags, t)
×
7399
        }
×
7400
        sort.Strings(tags)
×
7401

×
7402
        // Create the log levels string.
×
7403
        var logLevels []string
×
7404
        for _, t := range tags {
×
7405
                logLevels = append(logLevels, fmt.Sprintf("%s=%s", t,
×
7406
                        subLoggers[t].Level().String()))
×
7407
        }
×
7408
        logLevelsString := strings.Join(logLevels, ", ")
×
7409

×
7410
        // Propagate the new config level to the main config struct.
×
7411
        r.cfg.DebugLevel = logLevelsString
×
7412

×
7413
        return &lnrpc.DebugLevelResponse{
×
7414
                SubSystems: logLevelsString,
×
7415
        }, nil
×
7416
}
7417

7418
// DecodePayReq takes an encoded payment request string and attempts to decode
7419
// it, returning a full description of the conditions encoded within the
7420
// payment request.
7421
func (r *rpcServer) DecodePayReq(ctx context.Context,
7422
        req *lnrpc.PayReqString) (*lnrpc.PayReq, error) {
3✔
7423

3✔
7424
        rpcsLog.Tracef("[decodepayreq] decoding: %v", req.PayReq)
3✔
7425

3✔
7426
        // Fist we'll attempt to decode the payment request string, if the
3✔
7427
        // request is invalid or the checksum doesn't match, then we'll exit
3✔
7428
        // here with an error.
3✔
7429
        payReq, err := zpay32.Decode(req.PayReq, r.cfg.ActiveNetParams.Params)
3✔
7430
        if err != nil {
3✔
7431
                return nil, err
×
7432
        }
×
7433

7434
        // Let the fields default to empty strings.
7435
        desc := ""
3✔
7436
        if payReq.Description != nil {
6✔
7437
                desc = *payReq.Description
3✔
7438
        }
3✔
7439

7440
        descHash := []byte("")
3✔
7441
        if payReq.DescriptionHash != nil {
3✔
7442
                descHash = payReq.DescriptionHash[:]
×
7443
        }
×
7444

7445
        fallbackAddr := ""
3✔
7446
        if payReq.FallbackAddr != nil {
3✔
7447
                fallbackAddr = payReq.FallbackAddr.String()
×
7448
        }
×
7449

7450
        // Expiry time will default to 3600 seconds if not specified
7451
        // explicitly.
7452
        expiry := int64(payReq.Expiry().Seconds())
3✔
7453

3✔
7454
        // Convert between the `lnrpc` and `routing` types.
3✔
7455
        routeHints := invoicesrpc.CreateRPCRouteHints(payReq.RouteHints)
3✔
7456

3✔
7457
        blindedPaymentPaths, err := invoicesrpc.CreateRPCBlindedPayments(
3✔
7458
                payReq.BlindedPaymentPaths,
3✔
7459
        )
3✔
7460
        if err != nil {
3✔
7461
                return nil, err
×
7462
        }
×
7463

7464
        var amtSat, amtMsat int64
3✔
7465
        if payReq.MilliSat != nil {
6✔
7466
                amtSat = int64(payReq.MilliSat.ToSatoshis())
3✔
7467
                amtMsat = int64(*payReq.MilliSat)
3✔
7468
        }
3✔
7469

7470
        // Extract the payment address from the payment request, if present.
7471
        paymentAddr := payReq.PaymentAddr.UnwrapOr([32]byte{})
3✔
7472

3✔
7473
        dest := payReq.Destination.SerializeCompressed()
3✔
7474
        return &lnrpc.PayReq{
3✔
7475
                Destination:     hex.EncodeToString(dest),
3✔
7476
                PaymentHash:     hex.EncodeToString(payReq.PaymentHash[:]),
3✔
7477
                NumSatoshis:     amtSat,
3✔
7478
                NumMsat:         amtMsat,
3✔
7479
                Timestamp:       payReq.Timestamp.Unix(),
3✔
7480
                Description:     desc,
3✔
7481
                DescriptionHash: hex.EncodeToString(descHash[:]),
3✔
7482
                FallbackAddr:    fallbackAddr,
3✔
7483
                Expiry:          expiry,
3✔
7484
                CltvExpiry:      int64(payReq.MinFinalCLTVExpiry()),
3✔
7485
                RouteHints:      routeHints,
3✔
7486
                BlindedPaths:    blindedPaymentPaths,
3✔
7487
                PaymentAddr:     paymentAddr[:],
3✔
7488
                Features:        invoicesrpc.CreateRPCFeatures(payReq.Features),
3✔
7489
        }, nil
3✔
7490
}
7491

7492
// feeBase is the fixed point that fee rate computation are performed over.
7493
// Nodes on the network advertise their fee rate using this point as a base.
7494
// This means that the minimal possible fee rate if 1e-6, or 0.000001, or
7495
// 0.0001%.
7496
const feeBase float64 = 1000000
7497

7498
// FeeReport allows the caller to obtain a report detailing the current fee
7499
// schedule enforced by the node globally for each channel.
7500
func (r *rpcServer) FeeReport(ctx context.Context,
7501
        _ *lnrpc.FeeReportRequest) (*lnrpc.FeeReportResponse, error) {
3✔
7502

3✔
7503
        channelGraph := r.server.graphDB
3✔
7504
        selfNode, err := channelGraph.SourceNode()
3✔
7505
        if err != nil {
3✔
7506
                return nil, err
×
7507
        }
×
7508

7509
        var feeReports []*lnrpc.ChannelFeeReport
3✔
7510
        err = channelGraph.ForEachNodeChannel(selfNode.PubKeyBytes,
3✔
7511
                func(_ kvdb.RTx, chanInfo *models.ChannelEdgeInfo,
3✔
7512
                        edgePolicy, _ *models.ChannelEdgePolicy) error {
6✔
7513

3✔
7514
                        // Self node should always have policies for its
3✔
7515
                        // channels.
3✔
7516
                        if edgePolicy == nil {
3✔
7517
                                return fmt.Errorf("no policy for outgoing "+
×
7518
                                        "channel %v ", chanInfo.ChannelID)
×
7519
                        }
×
7520

7521
                        // We'll compute the effective fee rate by converting
7522
                        // from a fixed point fee rate to a floating point fee
7523
                        // rate. The fee rate field in the database the amount
7524
                        // of mSAT charged per 1mil mSAT sent, so will divide by
7525
                        // this to get the proper fee rate.
7526
                        feeRateFixedPoint :=
3✔
7527
                                edgePolicy.FeeProportionalMillionths
3✔
7528
                        feeRate := float64(feeRateFixedPoint) / feeBase
3✔
7529

3✔
7530
                        // Decode inbound fee from extra data.
3✔
7531
                        var inboundFee lnwire.Fee
3✔
7532
                        _, err := edgePolicy.ExtraOpaqueData.ExtractRecords(
3✔
7533
                                &inboundFee,
3✔
7534
                        )
3✔
7535
                        if err != nil {
3✔
7536
                                return err
×
7537
                        }
×
7538

7539
                        // TODO(roasbeef): also add stats for revenue for each
7540
                        // channel
7541
                        feeReports = append(feeReports, &lnrpc.ChannelFeeReport{
3✔
7542
                                ChanId:       chanInfo.ChannelID,
3✔
7543
                                ChannelPoint: chanInfo.ChannelPoint.String(),
3✔
7544
                                BaseFeeMsat:  int64(edgePolicy.FeeBaseMSat),
3✔
7545
                                FeePerMil:    int64(feeRateFixedPoint),
3✔
7546
                                FeeRate:      feeRate,
3✔
7547

3✔
7548
                                InboundBaseFeeMsat: inboundFee.BaseFee,
3✔
7549
                                InboundFeePerMil:   inboundFee.FeeRate,
3✔
7550
                        })
3✔
7551

3✔
7552
                        return nil
3✔
7553
                },
7554
        )
7555
        if err != nil {
3✔
7556
                return nil, err
×
7557
        }
×
7558

7559
        fwdEventLog := r.server.miscDB.ForwardingLog()
3✔
7560

3✔
7561
        // computeFeeSum is a helper function that computes the total fees for
3✔
7562
        // a particular time slice described by a forwarding event query.
3✔
7563
        computeFeeSum := func(query channeldb.ForwardingEventQuery) (lnwire.MilliSatoshi, error) {
6✔
7564

3✔
7565
                var totalFees lnwire.MilliSatoshi
3✔
7566

3✔
7567
                // We'll continue to fetch the next query and accumulate the
3✔
7568
                // fees until the next query returns no events.
3✔
7569
                for {
6✔
7570
                        timeSlice, err := fwdEventLog.Query(query)
3✔
7571
                        if err != nil {
3✔
7572
                                return 0, err
×
7573
                        }
×
7574

7575
                        // If the timeslice is empty, then we'll return as
7576
                        // we've retrieved all the entries in this range.
7577
                        if len(timeSlice.ForwardingEvents) == 0 {
6✔
7578
                                break
3✔
7579
                        }
7580

7581
                        // Otherwise, we'll tally up an accumulate the total
7582
                        // fees for this time slice.
7583
                        for _, event := range timeSlice.ForwardingEvents {
6✔
7584
                                fee := event.AmtIn - event.AmtOut
3✔
7585
                                totalFees += fee
3✔
7586
                        }
3✔
7587

7588
                        // We'll now take the last offset index returned as
7589
                        // part of this response, and modify our query to start
7590
                        // at this index. This has a pagination effect in the
7591
                        // case that our query bounds has more than 100k
7592
                        // entries.
7593
                        query.IndexOffset = timeSlice.LastIndexOffset
3✔
7594
                }
7595

7596
                return totalFees, nil
3✔
7597
        }
7598

7599
        now := time.Now()
3✔
7600

3✔
7601
        // Before we perform the queries below, we'll instruct the switch to
3✔
7602
        // flush any pending events to disk. This ensure we get a complete
3✔
7603
        // snapshot at this particular time.
3✔
7604
        if err := r.server.htlcSwitch.FlushForwardingEvents(); err != nil {
3✔
7605
                return nil, fmt.Errorf("unable to flush forwarding "+
×
7606
                        "events: %v", err)
×
7607
        }
×
7608

7609
        // In addition to returning the current fee schedule for each channel.
7610
        // We'll also perform a series of queries to obtain the total fees
7611
        // earned over the past day, week, and month.
7612
        dayQuery := channeldb.ForwardingEventQuery{
3✔
7613
                StartTime:    now.Add(-time.Hour * 24),
3✔
7614
                EndTime:      now,
3✔
7615
                NumMaxEvents: 1000,
3✔
7616
        }
3✔
7617
        dayFees, err := computeFeeSum(dayQuery)
3✔
7618
        if err != nil {
3✔
7619
                return nil, fmt.Errorf("unable to retrieve day fees: %w", err)
×
7620
        }
×
7621

7622
        weekQuery := channeldb.ForwardingEventQuery{
3✔
7623
                StartTime:    now.Add(-time.Hour * 24 * 7),
3✔
7624
                EndTime:      now,
3✔
7625
                NumMaxEvents: 1000,
3✔
7626
        }
3✔
7627
        weekFees, err := computeFeeSum(weekQuery)
3✔
7628
        if err != nil {
3✔
7629
                return nil, fmt.Errorf("unable to retrieve day fees: %w", err)
×
7630
        }
×
7631

7632
        monthQuery := channeldb.ForwardingEventQuery{
3✔
7633
                StartTime:    now.Add(-time.Hour * 24 * 30),
3✔
7634
                EndTime:      now,
3✔
7635
                NumMaxEvents: 1000,
3✔
7636
        }
3✔
7637
        monthFees, err := computeFeeSum(monthQuery)
3✔
7638
        if err != nil {
3✔
7639
                return nil, fmt.Errorf("unable to retrieve day fees: %w", err)
×
7640
        }
×
7641

7642
        return &lnrpc.FeeReportResponse{
3✔
7643
                ChannelFees: feeReports,
3✔
7644
                DayFeeSum:   uint64(dayFees.ToSatoshis()),
3✔
7645
                WeekFeeSum:  uint64(weekFees.ToSatoshis()),
3✔
7646
                MonthFeeSum: uint64(monthFees.ToSatoshis()),
3✔
7647
        }, nil
3✔
7648
}
7649

7650
// minFeeRate is the smallest permitted fee rate within the network. This is
7651
// derived by the fact that fee rates are computed using a fixed point of
7652
// 1,000,000. As a result, the smallest representable fee rate is 1e-6, or
7653
// 0.000001, or 0.0001%.
7654
const minFeeRate = 1e-6
7655

7656
// UpdateChannelPolicy allows the caller to update the channel forwarding policy
7657
// for all channels globally, or a particular channel.
7658
func (r *rpcServer) UpdateChannelPolicy(ctx context.Context,
7659
        req *lnrpc.PolicyUpdateRequest) (*lnrpc.PolicyUpdateResponse, error) {
3✔
7660

3✔
7661
        var targetChans []wire.OutPoint
3✔
7662
        switch scope := req.Scope.(type) {
3✔
7663
        // If the request is targeting all active channels, then we don't need
7664
        // target any channels by their channel point.
7665
        case *lnrpc.PolicyUpdateRequest_Global:
3✔
7666

7667
        // Otherwise, we're targeting an individual channel by its channel
7668
        // point.
7669
        case *lnrpc.PolicyUpdateRequest_ChanPoint:
3✔
7670
                txid, err := lnrpc.GetChanPointFundingTxid(scope.ChanPoint)
3✔
7671
                if err != nil {
3✔
7672
                        return nil, err
×
7673
                }
×
7674
                targetChans = append(targetChans, wire.OutPoint{
3✔
7675
                        Hash:  *txid,
3✔
7676
                        Index: scope.ChanPoint.OutputIndex,
3✔
7677
                })
3✔
7678
        default:
×
7679
                return nil, fmt.Errorf("unknown scope: %v", scope)
×
7680
        }
7681

7682
        var feeRateFixed uint32
3✔
7683

3✔
7684
        switch {
3✔
7685
        // The request should use either the fee rate in percent, or the new
7686
        // ppm rate, but not both.
7687
        case req.FeeRate != 0 && req.FeeRatePpm != 0:
×
7688
                errMsg := "cannot set both FeeRate and FeeRatePpm at the " +
×
7689
                        "same time"
×
7690

×
7691
                return nil, status.Errorf(codes.InvalidArgument, errMsg)
×
7692

7693
        // If the request is using fee_rate.
7694
        case req.FeeRate != 0:
3✔
7695
                // As a sanity check, if the fee isn't zero, we'll ensure that
3✔
7696
                // the passed fee rate is below 1e-6, or the lowest allowed
3✔
7697
                // non-zero fee rate expressible within the protocol.
3✔
7698
                if req.FeeRate != 0 && req.FeeRate < minFeeRate {
3✔
7699
                        return nil, fmt.Errorf("fee rate of %v is too "+
×
7700
                                "small, min fee rate is %v", req.FeeRate,
×
7701
                                minFeeRate)
×
7702
                }
×
7703

7704
                // We'll also need to convert the floating point fee rate we
7705
                // accept over RPC to the fixed point rate that we use within
7706
                // the protocol. We do this by multiplying the passed fee rate
7707
                // by the fee base. This gives us the fixed point, scaled by 1
7708
                // million that's used within the protocol.
7709
                //
7710
                // Because of the inaccurate precision of the IEEE 754
7711
                // standard, we need to round the product of feerate and
7712
                // feebase.
7713
                feeRateFixed = uint32(math.Round(req.FeeRate * feeBase))
3✔
7714

7715
        // Otherwise, we use the fee_rate_ppm parameter.
7716
        case req.FeeRatePpm != 0:
3✔
7717
                feeRateFixed = req.FeeRatePpm
3✔
7718
        }
7719

7720
        // We'll also ensure that the user isn't setting a CLTV delta that
7721
        // won't give outgoing HTLCs enough time to fully resolve if needed.
7722
        if req.TimeLockDelta < minTimeLockDelta {
3✔
7723
                return nil, fmt.Errorf("time lock delta of %v is too small, "+
×
7724
                        "minimum supported is %v", req.TimeLockDelta,
×
7725
                        minTimeLockDelta)
×
7726
        } else if req.TimeLockDelta > uint32(MaxTimeLockDelta) {
3✔
7727
                return nil, fmt.Errorf("time lock delta of %v is too big, "+
×
7728
                        "maximum supported is %v", req.TimeLockDelta,
×
7729
                        MaxTimeLockDelta)
×
7730
        }
×
7731

7732
        // By default, positive inbound fees are rejected.
7733
        if !r.cfg.AcceptPositiveInboundFees && req.InboundFee != nil {
6✔
7734
                if req.InboundFee.BaseFeeMsat > 0 {
3✔
7735
                        return nil, fmt.Errorf("positive values for inbound "+
×
7736
                                "base fee msat are not supported: %v",
×
7737
                                req.InboundFee.BaseFeeMsat)
×
7738
                }
×
7739
                if req.InboundFee.FeeRatePpm > 0 {
3✔
7740
                        return nil, fmt.Errorf("positive values for inbound "+
×
7741
                                "fee rate ppm are not supported: %v",
×
7742
                                req.InboundFee.FeeRatePpm)
×
7743
                }
×
7744
        }
7745

7746
        // If no inbound fees have been specified, we indicate with an empty
7747
        // option that the previous inbound fee should be retained during the
7748
        // edge update.
7749
        inboundFee := fn.None[models.InboundFee]()
3✔
7750
        if req.InboundFee != nil {
6✔
7751
                inboundFee = fn.Some(models.InboundFee{
3✔
7752
                        Base: req.InboundFee.BaseFeeMsat,
3✔
7753
                        Rate: req.InboundFee.FeeRatePpm,
3✔
7754
                })
3✔
7755
        }
3✔
7756

7757
        baseFeeMsat := lnwire.MilliSatoshi(req.BaseFeeMsat)
3✔
7758
        feeSchema := routing.FeeSchema{
3✔
7759
                BaseFee:    baseFeeMsat,
3✔
7760
                FeeRate:    feeRateFixed,
3✔
7761
                InboundFee: inboundFee,
3✔
7762
        }
3✔
7763

3✔
7764
        maxHtlc := lnwire.MilliSatoshi(req.MaxHtlcMsat)
3✔
7765
        var minHtlc *lnwire.MilliSatoshi
3✔
7766
        if req.MinHtlcMsatSpecified {
3✔
7767
                min := lnwire.MilliSatoshi(req.MinHtlcMsat)
×
7768
                minHtlc = &min
×
7769
        }
×
7770

7771
        chanPolicy := routing.ChannelPolicy{
3✔
7772
                FeeSchema:     feeSchema,
3✔
7773
                TimeLockDelta: req.TimeLockDelta,
3✔
7774
                MaxHTLC:       maxHtlc,
3✔
7775
                MinHTLC:       minHtlc,
3✔
7776
        }
3✔
7777

3✔
7778
        rpcsLog.Debugf("[updatechanpolicy] updating channel policy "+
3✔
7779
                "base_fee=%v, rate_fixed=%v, time_lock_delta: %v, "+
3✔
7780
                "min_htlc=%v, max_htlc=%v, targets=%v",
3✔
7781
                req.BaseFeeMsat, feeRateFixed, req.TimeLockDelta,
3✔
7782
                minHtlc, maxHtlc,
3✔
7783
                spew.Sdump(targetChans))
3✔
7784

3✔
7785
        // With the scope resolved, we'll now send this to the local channel
3✔
7786
        // manager so it can propagate the new policy for our target channel(s).
3✔
7787
        failedUpdates, err := r.server.localChanMgr.UpdatePolicy(chanPolicy,
3✔
7788
                req.CreateMissingEdge, targetChans...)
3✔
7789
        if err != nil {
3✔
7790
                return nil, err
×
7791
        }
×
7792

7793
        return &lnrpc.PolicyUpdateResponse{
3✔
7794
                FailedUpdates: failedUpdates,
3✔
7795
        }, nil
3✔
7796
}
7797

7798
// ForwardingHistory allows the caller to query the htlcswitch for a record of
7799
// all HTLC's forwarded within the target time range, and integer offset within
7800
// that time range. If no time-range is specified, then the first chunk of the
7801
// past 24 hrs of forwarding history are returned.
7802

7803
// A list of forwarding events are returned. The size of each forwarding event
7804
// is 40 bytes, and the max message size able to be returned in gRPC is 4 MiB.
7805
// In order to safely stay under this max limit, we'll return 50k events per
7806
// response.  Each response has the index offset of the last entry. The index
7807
// offset can be provided to the request to allow the caller to skip a series
7808
// of records.
7809
func (r *rpcServer) ForwardingHistory(ctx context.Context,
7810
        req *lnrpc.ForwardingHistoryRequest) (*lnrpc.ForwardingHistoryResponse,
7811
        error) {
3✔
7812

3✔
7813
        // Before we perform the queries below, we'll instruct the switch to
3✔
7814
        // flush any pending events to disk. This ensure we get a complete
3✔
7815
        // snapshot at this particular time.
3✔
7816
        if err := r.server.htlcSwitch.FlushForwardingEvents(); err != nil {
3✔
7817
                return nil, fmt.Errorf("unable to flush forwarding "+
×
7818
                        "events: %v", err)
×
7819
        }
×
7820

7821
        var (
3✔
7822
                startTime, endTime time.Time
3✔
7823

3✔
7824
                numEvents uint32
3✔
7825
        )
3✔
7826

3✔
7827
        // startTime defaults to the Unix epoch (0 unixtime, or
3✔
7828
        // midnight 01-01-1970).
3✔
7829
        startTime = time.Unix(int64(req.StartTime), 0)
3✔
7830

3✔
7831
        // If the end time wasn't specified, assume a default end time of now.
3✔
7832
        if req.EndTime == 0 {
6✔
7833
                now := time.Now()
3✔
7834
                endTime = now
3✔
7835
        } else {
3✔
7836
                endTime = time.Unix(int64(req.EndTime), 0)
×
7837
        }
×
7838

7839
        // If the number of events wasn't specified, then we'll default to
7840
        // returning the last 100 events.
7841
        numEvents = req.NumMaxEvents
3✔
7842
        if numEvents == 0 {
6✔
7843
                numEvents = 100
3✔
7844
        }
3✔
7845

7846
        // Next, we'll map the proto request into a format that is understood by
7847
        // the forwarding log.
7848
        eventQuery := channeldb.ForwardingEventQuery{
3✔
7849
                StartTime:    startTime,
3✔
7850
                EndTime:      endTime,
3✔
7851
                IndexOffset:  req.IndexOffset,
3✔
7852
                NumMaxEvents: numEvents,
3✔
7853
        }
3✔
7854
        timeSlice, err := r.server.miscDB.ForwardingLog().Query(eventQuery)
3✔
7855
        if err != nil {
3✔
7856
                return nil, fmt.Errorf("unable to query forwarding log: %w",
×
7857
                        err)
×
7858
        }
×
7859

7860
        // chanToPeerAlias caches previously looked up channel information.
7861
        chanToPeerAlias := make(map[lnwire.ShortChannelID]string)
3✔
7862

3✔
7863
        // Helper function to extract a peer's node alias given its SCID.
3✔
7864
        getRemoteAlias := func(chanID lnwire.ShortChannelID) (string, error) {
6✔
7865
                // If we'd previously seen this chanID then return the cached
3✔
7866
                // peer alias.
3✔
7867
                if peerAlias, ok := chanToPeerAlias[chanID]; ok {
6✔
7868
                        return peerAlias, nil
3✔
7869
                }
3✔
7870

7871
                // Else call the server to look up the peer alias.
7872
                edge, err := r.GetChanInfo(ctx, &lnrpc.ChanInfoRequest{
3✔
7873
                        ChanId: chanID.ToUint64(),
3✔
7874
                })
3✔
7875
                if err != nil {
3✔
7876
                        return "", err
×
7877
                }
×
7878

7879
                remotePub := edge.Node1Pub
3✔
7880
                if r.selfNode.String() == edge.Node1Pub {
6✔
7881
                        remotePub = edge.Node2Pub
3✔
7882
                }
3✔
7883

7884
                vertex, err := route.NewVertexFromStr(remotePub)
3✔
7885
                if err != nil {
3✔
7886
                        return "", err
×
7887
                }
×
7888

7889
                peer, err := r.server.graphDB.FetchLightningNode(vertex)
3✔
7890
                if err != nil {
3✔
7891
                        return "", err
×
7892
                }
×
7893

7894
                // Cache the peer alias.
7895
                chanToPeerAlias[chanID] = peer.Alias
3✔
7896

3✔
7897
                return peer.Alias, nil
3✔
7898
        }
7899

7900
        // TODO(roasbeef): add settlement latency?
7901
        //  * use FPE on all records?
7902

7903
        // With the events retrieved, we'll now map them into the proper proto
7904
        // response.
7905
        //
7906
        // TODO(roasbeef): show in ns for the outside?
7907
        fwdingEvents := make(
3✔
7908
                []*lnrpc.ForwardingEvent, len(timeSlice.ForwardingEvents),
3✔
7909
        )
3✔
7910
        resp := &lnrpc.ForwardingHistoryResponse{
3✔
7911
                ForwardingEvents: fwdingEvents,
3✔
7912
                LastOffsetIndex:  timeSlice.LastIndexOffset,
3✔
7913
        }
3✔
7914
        for i, event := range timeSlice.ForwardingEvents {
6✔
7915
                amtInMsat := event.AmtIn
3✔
7916
                amtOutMsat := event.AmtOut
3✔
7917
                feeMsat := event.AmtIn - event.AmtOut
3✔
7918

3✔
7919
                resp.ForwardingEvents[i] = &lnrpc.ForwardingEvent{
3✔
7920
                        Timestamp:   uint64(event.Timestamp.Unix()),
3✔
7921
                        TimestampNs: uint64(event.Timestamp.UnixNano()),
3✔
7922
                        ChanIdIn:    event.IncomingChanID.ToUint64(),
3✔
7923
                        ChanIdOut:   event.OutgoingChanID.ToUint64(),
3✔
7924
                        AmtIn:       uint64(amtInMsat.ToSatoshis()),
3✔
7925
                        AmtOut:      uint64(amtOutMsat.ToSatoshis()),
3✔
7926
                        Fee:         uint64(feeMsat.ToSatoshis()),
3✔
7927
                        FeeMsat:     uint64(feeMsat),
3✔
7928
                        AmtInMsat:   uint64(amtInMsat),
3✔
7929
                        AmtOutMsat:  uint64(amtOutMsat),
3✔
7930
                }
3✔
7931

3✔
7932
                if req.PeerAliasLookup {
6✔
7933
                        aliasIn, err := getRemoteAlias(event.IncomingChanID)
3✔
7934
                        if err != nil {
3✔
7935
                                aliasIn = fmt.Sprintf("unable to lookup peer "+
×
7936
                                        "alias: %v", err)
×
7937
                        }
×
7938
                        aliasOut, err := getRemoteAlias(event.OutgoingChanID)
3✔
7939
                        if err != nil {
3✔
7940
                                aliasOut = fmt.Sprintf("unable to lookup peer"+
×
7941
                                        "alias: %v", err)
×
7942
                        }
×
7943
                        resp.ForwardingEvents[i].PeerAliasIn = aliasIn
3✔
7944
                        resp.ForwardingEvents[i].PeerAliasOut = aliasOut
3✔
7945
                }
7946
        }
7947

7948
        return resp, nil
3✔
7949
}
7950

7951
// ExportChannelBackup attempts to return an encrypted static channel backup
7952
// for the target channel identified by it channel point. The backup is
7953
// encrypted with a key generated from the aezeed seed of the user. The
7954
// returned backup can either be restored using the RestoreChannelBackup method
7955
// once lnd is running, or via the InitWallet and UnlockWallet methods from the
7956
// WalletUnlocker service.
7957
func (r *rpcServer) ExportChannelBackup(ctx context.Context,
7958
        in *lnrpc.ExportChannelBackupRequest) (*lnrpc.ChannelBackup, error) {
3✔
7959

3✔
7960
        // First, we'll convert the lnrpc channel point into a wire.OutPoint
3✔
7961
        // that we can manipulate.
3✔
7962
        txid, err := lnrpc.GetChanPointFundingTxid(in.ChanPoint)
3✔
7963
        if err != nil {
3✔
7964
                return nil, err
×
7965
        }
×
7966
        chanPoint := wire.OutPoint{
3✔
7967
                Hash:  *txid,
3✔
7968
                Index: in.ChanPoint.OutputIndex,
3✔
7969
        }
3✔
7970

3✔
7971
        // Next, we'll attempt to fetch a channel backup for this channel from
3✔
7972
        // the database. If this channel has been closed, or the outpoint is
3✔
7973
        // unknown, then we'll return an error
3✔
7974
        unpackedBackup, err := chanbackup.FetchBackupForChan(
3✔
7975
                chanPoint, r.server.chanStateDB, r.server.addrSource,
3✔
7976
        )
3✔
7977
        if err != nil {
3✔
7978
                return nil, err
×
7979
        }
×
7980

7981
        // At this point, we have an unpacked backup (plaintext) so we'll now
7982
        // attempt to serialize and encrypt it in order to create a packed
7983
        // backup.
7984
        packedBackups, err := chanbackup.PackStaticChanBackups(
3✔
7985
                []chanbackup.Single{*unpackedBackup},
3✔
7986
                r.server.cc.KeyRing,
3✔
7987
        )
3✔
7988
        if err != nil {
3✔
7989
                return nil, fmt.Errorf("packing of back ups failed: %w", err)
×
7990
        }
×
7991

7992
        // Before we proceed, we'll ensure that we received a backup for this
7993
        // channel, otherwise, we'll bail out.
7994
        packedBackup, ok := packedBackups[chanPoint]
3✔
7995
        if !ok {
3✔
7996
                return nil, fmt.Errorf("expected single backup for "+
×
7997
                        "ChannelPoint(%v), got %v", chanPoint,
×
7998
                        len(packedBackup))
×
7999
        }
×
8000

8001
        return &lnrpc.ChannelBackup{
3✔
8002
                ChanPoint:  in.ChanPoint,
3✔
8003
                ChanBackup: packedBackup,
3✔
8004
        }, nil
3✔
8005
}
8006

8007
// VerifyChanBackup allows a caller to verify the integrity of a channel backup
8008
// snapshot. This method will accept both either a packed Single or a packed
8009
// Multi. Specifying both will result in an error.
8010
func (r *rpcServer) VerifyChanBackup(ctx context.Context,
8011
        in *lnrpc.ChanBackupSnapshot) (*lnrpc.VerifyChanBackupResponse, error) {
3✔
8012

3✔
8013
        var (
3✔
8014
                channels []chanbackup.Single
3✔
8015
                err      error
3✔
8016
        )
3✔
8017
        switch {
3✔
8018
        // If neither a Single or Multi has been specified, then we have nothing
8019
        // to verify.
8020
        case in.GetSingleChanBackups() == nil && in.GetMultiChanBackup() == nil:
×
8021
                return nil, errors.New("either a Single or Multi channel " +
×
8022
                        "backup must be specified")
×
8023

8024
        // Either a Single or a Multi must be specified, but not both.
8025
        case in.GetSingleChanBackups() != nil && in.GetMultiChanBackup() != nil:
×
8026
                return nil, errors.New("either a Single or Multi channel " +
×
8027
                        "backup must be specified, but not both")
×
8028

8029
        // If a Single is specified then we'll only accept one of them to allow
8030
        // the caller to map the valid/invalid state for each individual Single.
8031
        case in.GetSingleChanBackups() != nil:
×
8032
                chanBackupsProtos := in.GetSingleChanBackups().ChanBackups
×
8033
                if len(chanBackupsProtos) != 1 {
×
8034
                        return nil, errors.New("only one Single is accepted " +
×
8035
                                "at a time")
×
8036
                }
×
8037

8038
                // First, we'll convert the raw byte slice into a type we can
8039
                // work with a bit better.
8040
                chanBackup := chanbackup.PackedSingles(
×
8041
                        [][]byte{chanBackupsProtos[0].ChanBackup},
×
8042
                )
×
8043

×
8044
                // With our PackedSingles created, we'll attempt to unpack the
×
8045
                // backup. If this fails, then we know the backup is invalid for
×
8046
                // some reason.
×
8047
                channels, err = chanBackup.Unpack(r.server.cc.KeyRing)
×
8048
                if err != nil {
×
8049
                        return nil, fmt.Errorf("invalid single channel "+
×
8050
                                "backup: %v", err)
×
8051
                }
×
8052

8053
        case in.GetMultiChanBackup() != nil:
3✔
8054
                // We'll convert the raw byte slice into a PackedMulti that we
3✔
8055
                // can easily work with.
3✔
8056
                packedMultiBackup := in.GetMultiChanBackup().MultiChanBackup
3✔
8057
                packedMulti := chanbackup.PackedMulti(packedMultiBackup)
3✔
8058

3✔
8059
                // We'll now attempt to unpack the Multi. If this fails, then we
3✔
8060
                // know it's invalid.
3✔
8061
                multi, err := packedMulti.Unpack(r.server.cc.KeyRing)
3✔
8062
                if err != nil {
3✔
8063
                        return nil, fmt.Errorf("invalid multi channel backup: "+
×
8064
                                "%v", err)
×
8065
                }
×
8066

8067
                channels = multi.StaticBackups
3✔
8068
        }
8069

8070
        return &lnrpc.VerifyChanBackupResponse{
3✔
8071
                ChanPoints: fn.Map(channels, func(c chanbackup.Single) string {
6✔
8072
                        return c.FundingOutpoint.String()
3✔
8073
                }),
3✔
8074
        }, nil
8075
}
8076

8077
// createBackupSnapshot converts the passed Single backup into a snapshot which
8078
// contains individual packed single backups, as well as a single packed multi
8079
// backup.
8080
func (r *rpcServer) createBackupSnapshot(backups []chanbackup.Single) (
8081
        *lnrpc.ChanBackupSnapshot, error) {
3✔
8082

3✔
8083
        // Once we have the set of back ups, we'll attempt to pack them all
3✔
8084
        // into a series of single channel backups.
3✔
8085
        singleChanPackedBackups, err := chanbackup.PackStaticChanBackups(
3✔
8086
                backups, r.server.cc.KeyRing,
3✔
8087
        )
3✔
8088
        if err != nil {
3✔
8089
                return nil, fmt.Errorf("unable to pack set of chan "+
×
8090
                        "backups: %v", err)
×
8091
        }
×
8092

8093
        // Now that we have our set of single packed backups, we'll morph that
8094
        // into a form that the proto response requires.
8095
        numBackups := len(singleChanPackedBackups)
3✔
8096
        singleBackupResp := &lnrpc.ChannelBackups{
3✔
8097
                ChanBackups: make([]*lnrpc.ChannelBackup, 0, numBackups),
3✔
8098
        }
3✔
8099
        for chanPoint, singlePackedBackup := range singleChanPackedBackups {
6✔
8100
                txid := chanPoint.Hash
3✔
8101
                rpcChanPoint := &lnrpc.ChannelPoint{
3✔
8102
                        FundingTxid: &lnrpc.ChannelPoint_FundingTxidBytes{
3✔
8103
                                FundingTxidBytes: txid[:],
3✔
8104
                        },
3✔
8105
                        OutputIndex: chanPoint.Index,
3✔
8106
                }
3✔
8107

3✔
8108
                singleBackupResp.ChanBackups = append(
3✔
8109
                        singleBackupResp.ChanBackups,
3✔
8110
                        &lnrpc.ChannelBackup{
3✔
8111
                                ChanPoint:  rpcChanPoint,
3✔
8112
                                ChanBackup: singlePackedBackup,
3✔
8113
                        },
3✔
8114
                )
3✔
8115
        }
3✔
8116

8117
        // In addition, to the set of single chan backups, we'll also create a
8118
        // single multi-channel backup which can be serialized into a single
8119
        // file for safe storage.
8120
        var b bytes.Buffer
3✔
8121
        unpackedMultiBackup := chanbackup.Multi{
3✔
8122
                StaticBackups: backups,
3✔
8123
        }
3✔
8124
        err = unpackedMultiBackup.PackToWriter(&b, r.server.cc.KeyRing)
3✔
8125
        if err != nil {
3✔
8126
                return nil, fmt.Errorf("unable to multi-pack backups: %w", err)
×
8127
        }
×
8128

8129
        multiBackupResp := &lnrpc.MultiChanBackup{
3✔
8130
                MultiChanBackup: b.Bytes(),
3✔
8131
        }
3✔
8132
        for _, singleBackup := range singleBackupResp.ChanBackups {
6✔
8133
                multiBackupResp.ChanPoints = append(
3✔
8134
                        multiBackupResp.ChanPoints, singleBackup.ChanPoint,
3✔
8135
                )
3✔
8136
        }
3✔
8137

8138
        return &lnrpc.ChanBackupSnapshot{
3✔
8139
                SingleChanBackups: singleBackupResp,
3✔
8140
                MultiChanBackup:   multiBackupResp,
3✔
8141
        }, nil
3✔
8142
}
8143

8144
// ExportAllChannelBackups returns static channel backups for all existing
8145
// channels known to lnd. A set of regular singular static channel backups for
8146
// each channel are returned. Additionally, a multi-channel backup is returned
8147
// as well, which contains a single encrypted blob containing the backups of
8148
// each channel.
8149
func (r *rpcServer) ExportAllChannelBackups(ctx context.Context,
8150
        in *lnrpc.ChanBackupExportRequest) (*lnrpc.ChanBackupSnapshot, error) {
3✔
8151

3✔
8152
        // First, we'll attempt to read back ups for ALL currently opened
3✔
8153
        // channels from disk.
3✔
8154
        allUnpackedBackups, err := chanbackup.FetchStaticChanBackups(
3✔
8155
                r.server.chanStateDB, r.server.addrSource,
3✔
8156
        )
3✔
8157
        if err != nil {
3✔
8158
                return nil, fmt.Errorf("unable to fetch all static chan "+
×
8159
                        "backups: %v", err)
×
8160
        }
×
8161

8162
        // With the backups assembled, we'll create a full snapshot.
8163
        return r.createBackupSnapshot(allUnpackedBackups)
3✔
8164
}
8165

8166
// RestoreChannelBackups accepts a set of singular channel backups, or a single
8167
// encrypted multi-chan backup and attempts to recover any funds remaining
8168
// within the channel. If we're able to unpack the backup, then the new channel
8169
// will be shown under listchannels, as well as pending channels.
8170
func (r *rpcServer) RestoreChannelBackups(ctx context.Context,
8171
        in *lnrpc.RestoreChanBackupRequest) (*lnrpc.RestoreBackupResponse, error) {
3✔
8172

3✔
8173
        // The server hasn't yet started, so it won't be able to service any of
3✔
8174
        // our requests, so we'll bail early here.
3✔
8175
        if !r.server.Started() {
3✔
8176
                return nil, ErrServerNotActive
×
8177
        }
×
8178

8179
        // First, we'll make our implementation of the
8180
        // chanbackup.ChannelRestorer interface which we'll use to properly
8181
        // restore either a set of chanbackup.Single or chanbackup.Multi
8182
        // backups.
8183
        chanRestorer := &chanDBRestorer{
3✔
8184
                db:         r.server.chanStateDB,
3✔
8185
                secretKeys: r.server.cc.KeyRing,
3✔
8186
                chainArb:   r.server.chainArb,
3✔
8187
        }
3✔
8188

3✔
8189
        // We'll accept either a list of Single backups, or a single Multi
3✔
8190
        // backup which contains several single backups.
3✔
8191
        var (
3✔
8192
                numRestored int
3✔
8193
                err         error
3✔
8194
        )
3✔
8195
        switch {
3✔
8196
        case in.GetChanBackups() != nil:
×
8197
                chanBackupsProtos := in.GetChanBackups()
×
8198

×
8199
                // Now that we know what type of backup we're working with,
×
8200
                // we'll parse them all out into a more suitable format.
×
8201
                packedBackups := make([][]byte, 0, len(chanBackupsProtos.ChanBackups))
×
8202
                for _, chanBackup := range chanBackupsProtos.ChanBackups {
×
8203
                        packedBackups = append(
×
8204
                                packedBackups, chanBackup.ChanBackup,
×
8205
                        )
×
8206
                }
×
8207

8208
                // With our backups obtained, we'll now restore them which will
8209
                // write the new backups to disk, and then attempt to connect
8210
                // out to any peers that we know of which were our prior
8211
                // channel peers.
8212
                numRestored, err = chanbackup.UnpackAndRecoverSingles(
×
8213
                        chanbackup.PackedSingles(packedBackups),
×
8214
                        r.server.cc.KeyRing, chanRestorer, r.server,
×
8215
                )
×
8216
                if err != nil {
×
8217
                        return nil, fmt.Errorf("unable to unpack single "+
×
8218
                                "backups: %v", err)
×
8219
                }
×
8220

8221
        case in.GetMultiChanBackup() != nil:
3✔
8222
                packedMultiBackup := in.GetMultiChanBackup()
3✔
8223

3✔
8224
                // With our backups obtained, we'll now restore them which will
3✔
8225
                // write the new backups to disk, and then attempt to connect
3✔
8226
                // out to any peers that we know of which were our prior
3✔
8227
                // channel peers.
3✔
8228
                packedMulti := chanbackup.PackedMulti(packedMultiBackup)
3✔
8229
                numRestored, err = chanbackup.UnpackAndRecoverMulti(
3✔
8230
                        packedMulti, r.server.cc.KeyRing, chanRestorer,
3✔
8231
                        r.server,
3✔
8232
                )
3✔
8233
                if err != nil {
3✔
8234
                        return nil, fmt.Errorf("unable to unpack chan "+
×
8235
                                "backup: %v", err)
×
8236
                }
×
8237
        }
8238

8239
        return &lnrpc.RestoreBackupResponse{
3✔
8240
                NumRestored: uint32(numRestored),
3✔
8241
        }, nil
3✔
8242
}
8243

8244
// SubscribeChannelBackups allows a client to sub-subscribe to the most up to
8245
// date information concerning the state of all channel back ups. Each time a
8246
// new channel is added, we return the new set of channels, along with a
8247
// multi-chan backup containing the backup info for all channels. Each time a
8248
// channel is closed, we send a new update, which contains new new chan back
8249
// ups, but the updated set of encrypted multi-chan backups with the closed
8250
// channel(s) removed.
8251
func (r *rpcServer) SubscribeChannelBackups(req *lnrpc.ChannelBackupSubscription,
8252
        updateStream lnrpc.Lightning_SubscribeChannelBackupsServer) error {
3✔
8253

3✔
8254
        // First, we'll subscribe to the primary channel notifier so we can
3✔
8255
        // obtain events for new pending/opened/closed channels.
3✔
8256
        chanSubscription, err := r.server.channelNotifier.SubscribeChannelEvents()
3✔
8257
        if err != nil {
3✔
8258
                return err
×
8259
        }
×
8260

8261
        defer chanSubscription.Cancel()
3✔
8262
        for {
6✔
8263
                select {
3✔
8264
                // A new event has been sent by the channel notifier, we'll
8265
                // assemble, then sling out a new event to the client.
8266
                case e := <-chanSubscription.Updates():
3✔
8267
                        // TODO(roasbeef): batch dispatch ntnfs
3✔
8268

3✔
8269
                        switch e.(type) {
3✔
8270

8271
                        // We only care about new/closed channels, so we'll
8272
                        // skip any events for active/inactive channels.
8273
                        // To make the subscription behave the same way as the
8274
                        // synchronous call and the file based backup, we also
8275
                        // include pending channels in the update.
8276
                        case channelnotifier.ActiveChannelEvent:
3✔
8277
                                continue
3✔
8278
                        case channelnotifier.InactiveChannelEvent:
3✔
8279
                                continue
3✔
8280
                        case channelnotifier.ActiveLinkEvent:
3✔
8281
                                continue
3✔
8282
                        case channelnotifier.InactiveLinkEvent:
3✔
8283
                                continue
3✔
8284
                        }
8285

8286
                        // Now that we know the channel state has changed,
8287
                        // we'll obtains the current set of single channel
8288
                        // backups from disk.
8289
                        chanBackups, err := chanbackup.FetchStaticChanBackups(
3✔
8290
                                r.server.chanStateDB, r.server.addrSource,
3✔
8291
                        )
3✔
8292
                        if err != nil {
3✔
8293
                                return fmt.Errorf("unable to fetch all "+
×
8294
                                        "static chan backups: %v", err)
×
8295
                        }
×
8296

8297
                        // With our backups obtained, we'll pack them into a
8298
                        // snapshot and send them back to the client.
8299
                        backupSnapshot, err := r.createBackupSnapshot(
3✔
8300
                                chanBackups,
3✔
8301
                        )
3✔
8302
                        if err != nil {
3✔
8303
                                return err
×
8304
                        }
×
8305
                        err = updateStream.Send(backupSnapshot)
3✔
8306
                        if err != nil {
3✔
8307
                                return err
×
8308
                        }
×
8309

8310
                // The response stream's context for whatever reason has been
8311
                // closed. If context is closed by an exceeded deadline we will
8312
                // return an error.
8313
                case <-updateStream.Context().Done():
3✔
8314
                        if errors.Is(updateStream.Context().Err(), context.Canceled) {
6✔
8315
                                return nil
3✔
8316
                        }
3✔
8317
                        return updateStream.Context().Err()
×
8318

8319
                case <-r.quit:
×
8320
                        return nil
×
8321
                }
8322
        }
8323
}
8324

8325
// ChannelAcceptor dispatches a bi-directional streaming RPC in which
8326
// OpenChannel requests are sent to the client and the client responds with
8327
// a boolean that tells LND whether or not to accept the channel. This allows
8328
// node operators to specify their own criteria for accepting inbound channels
8329
// through a single persistent connection.
8330
func (r *rpcServer) ChannelAcceptor(stream lnrpc.Lightning_ChannelAcceptorServer) error {
3✔
8331
        chainedAcceptor := r.chanPredicate
3✔
8332

3✔
8333
        // Create a new RPCAcceptor which will send requests into the
3✔
8334
        // newRequests channel when it receives them.
3✔
8335
        rpcAcceptor := chanacceptor.NewRPCAcceptor(
3✔
8336
                stream.Recv, stream.Send, r.cfg.AcceptorTimeout,
3✔
8337
                r.cfg.ActiveNetParams.Params, r.quit,
3✔
8338
        )
3✔
8339

3✔
8340
        // Add the RPCAcceptor to the ChainedAcceptor and defer its removal.
3✔
8341
        id := chainedAcceptor.AddAcceptor(rpcAcceptor)
3✔
8342
        defer chainedAcceptor.RemoveAcceptor(id)
3✔
8343

3✔
8344
        // Run the rpc acceptor, which will accept requests for channel
3✔
8345
        // acceptance decisions from our chained acceptor, send them to the
3✔
8346
        // channel acceptor and listen for and report responses. This function
3✔
8347
        // blocks, and will exit if the rpcserver receives the instruction to
3✔
8348
        // shutdown, or the client cancels.
3✔
8349
        return rpcAcceptor.Run()
3✔
8350
}
3✔
8351

8352
// BakeMacaroon allows the creation of a new macaroon with custom read and write
8353
// permissions. No first-party caveats are added since this can be done offline.
8354
// If the --allow-external-permissions flag is set, the RPC will allow
8355
// external permissions that LND is not aware of.
8356
func (r *rpcServer) BakeMacaroon(ctx context.Context,
8357
        req *lnrpc.BakeMacaroonRequest) (*lnrpc.BakeMacaroonResponse, error) {
3✔
8358

3✔
8359
        // If the --no-macaroons flag is used to start lnd, the macaroon service
3✔
8360
        // is not initialized. Therefore we can't bake new macaroons.
3✔
8361
        if r.macService == nil {
3✔
8362
                return nil, errMacaroonDisabled
×
8363
        }
×
8364

8365
        helpMsg := fmt.Sprintf("supported actions are %v, supported entities "+
3✔
8366
                "are %v", validActions, validEntities)
3✔
8367

3✔
8368
        // Don't allow empty permission list as it doesn't make sense to have
3✔
8369
        // a macaroon that is not allowed to access any RPC.
3✔
8370
        if len(req.Permissions) == 0 {
6✔
8371
                return nil, fmt.Errorf("permission list cannot be empty. "+
3✔
8372
                        "specify at least one action/entity pair. %s", helpMsg)
3✔
8373
        }
3✔
8374

8375
        // Validate and map permission struct used by gRPC to the one used by
8376
        // the bakery. If the --allow-external-permissions flag is set, we
8377
        // will not validate, but map.
8378
        requestedPermissions := make([]bakery.Op, len(req.Permissions))
3✔
8379
        for idx, op := range req.Permissions {
6✔
8380
                if req.AllowExternalPermissions {
6✔
8381
                        requestedPermissions[idx] = bakery.Op{
3✔
8382
                                Entity: op.Entity,
3✔
8383
                                Action: op.Action,
3✔
8384
                        }
3✔
8385
                        continue
3✔
8386
                }
8387

8388
                if !stringInSlice(op.Entity, validEntities) {
6✔
8389
                        return nil, fmt.Errorf("invalid permission entity. %s",
3✔
8390
                                helpMsg)
3✔
8391
                }
3✔
8392

8393
                // Either we have the special entity "uri" which specifies a
8394
                // full gRPC URI or we have one of the pre-defined actions.
8395
                if op.Entity == macaroons.PermissionEntityCustomURI {
6✔
8396
                        allPermissions := r.interceptorChain.Permissions()
3✔
8397
                        _, ok := allPermissions[op.Action]
3✔
8398
                        if !ok {
3✔
8399
                                return nil, fmt.Errorf("invalid permission " +
×
8400
                                        "action, must be an existing URI in " +
×
8401
                                        "the format /package.Service/" +
×
8402
                                        "MethodName")
×
8403
                        }
×
8404
                } else if !stringInSlice(op.Action, validActions) {
6✔
8405
                        return nil, fmt.Errorf("invalid permission action. %s",
3✔
8406
                                helpMsg)
3✔
8407
                }
3✔
8408

8409
                requestedPermissions[idx] = bakery.Op{
3✔
8410
                        Entity: op.Entity,
3✔
8411
                        Action: op.Action,
3✔
8412
                }
3✔
8413
        }
8414

8415
        // Convert root key id from uint64 to bytes. Because the
8416
        // DefaultRootKeyID is a digit 0 expressed in a byte slice of a string
8417
        // "0", we will keep the IDs in the same format - all must be numeric,
8418
        // and must be a byte slice of string value of the digit, e.g.,
8419
        // uint64(123) to string(123).
8420
        rootKeyID := []byte(strconv.FormatUint(req.RootKeyId, 10))
3✔
8421

3✔
8422
        // Bake new macaroon with the given permissions and send it binary
3✔
8423
        // serialized and hex encoded to the client.
3✔
8424
        newMac, err := r.macService.NewMacaroon(
3✔
8425
                ctx, rootKeyID, requestedPermissions...,
3✔
8426
        )
3✔
8427
        if err != nil {
3✔
8428
                return nil, err
×
8429
        }
×
8430
        newMacBytes, err := newMac.M().MarshalBinary()
3✔
8431
        if err != nil {
3✔
8432
                return nil, err
×
8433
        }
×
8434
        resp := &lnrpc.BakeMacaroonResponse{}
3✔
8435
        resp.Macaroon = hex.EncodeToString(newMacBytes)
3✔
8436

3✔
8437
        return resp, nil
3✔
8438
}
8439

8440
// ListMacaroonIDs returns a list of macaroon root key IDs in use.
8441
func (r *rpcServer) ListMacaroonIDs(ctx context.Context,
8442
        req *lnrpc.ListMacaroonIDsRequest) (
8443
        *lnrpc.ListMacaroonIDsResponse, error) {
3✔
8444

3✔
8445
        // If the --no-macaroons flag is used to start lnd, the macaroon service
3✔
8446
        // is not initialized. Therefore we can't show any IDs.
3✔
8447
        if r.macService == nil {
3✔
8448
                return nil, errMacaroonDisabled
×
8449
        }
×
8450

8451
        rootKeyIDByteSlice, err := r.macService.ListMacaroonIDs(ctx)
3✔
8452
        if err != nil {
3✔
8453
                return nil, err
×
8454
        }
×
8455

8456
        var rootKeyIDs []uint64
3✔
8457
        for _, value := range rootKeyIDByteSlice {
6✔
8458
                // Convert bytes into uint64.
3✔
8459
                id, err := strconv.ParseUint(string(value), 10, 64)
3✔
8460
                if err != nil {
3✔
8461
                        return nil, err
×
8462
                }
×
8463

8464
                rootKeyIDs = append(rootKeyIDs, id)
3✔
8465
        }
8466

8467
        return &lnrpc.ListMacaroonIDsResponse{RootKeyIds: rootKeyIDs}, nil
3✔
8468
}
8469

8470
// DeleteMacaroonID removes a specific macaroon ID.
8471
func (r *rpcServer) DeleteMacaroonID(ctx context.Context,
8472
        req *lnrpc.DeleteMacaroonIDRequest) (
8473
        *lnrpc.DeleteMacaroonIDResponse, error) {
3✔
8474

3✔
8475
        // If the --no-macaroons flag is used to start lnd, the macaroon service
3✔
8476
        // is not initialized. Therefore we can't delete any IDs.
3✔
8477
        if r.macService == nil {
3✔
8478
                return nil, errMacaroonDisabled
×
8479
        }
×
8480

8481
        // Convert root key id from uint64 to bytes. Because the
8482
        // DefaultRootKeyID is a digit 0 expressed in a byte slice of a string
8483
        // "0", we will keep the IDs in the same format - all must be digit, and
8484
        // must be a byte slice of string value of the digit.
8485
        rootKeyID := []byte(strconv.FormatUint(req.RootKeyId, 10))
3✔
8486
        deletedIDBytes, err := r.macService.DeleteMacaroonID(ctx, rootKeyID)
3✔
8487
        if err != nil {
6✔
8488
                return nil, err
3✔
8489
        }
3✔
8490

8491
        return &lnrpc.DeleteMacaroonIDResponse{
3✔
8492
                // If the root key ID doesn't exist, it won't be deleted. We
3✔
8493
                // will return a response with deleted = false, otherwise true.
3✔
8494
                Deleted: deletedIDBytes != nil,
3✔
8495
        }, nil
3✔
8496
}
8497

8498
// ListPermissions lists all RPC method URIs and their required macaroon
8499
// permissions to access them.
8500
func (r *rpcServer) ListPermissions(_ context.Context,
8501
        _ *lnrpc.ListPermissionsRequest) (*lnrpc.ListPermissionsResponse,
8502
        error) {
3✔
8503

3✔
8504
        permissionMap := make(map[string]*lnrpc.MacaroonPermissionList)
3✔
8505
        for uri, perms := range r.interceptorChain.Permissions() {
6✔
8506
                rpcPerms := make([]*lnrpc.MacaroonPermission, len(perms))
3✔
8507
                for idx, perm := range perms {
6✔
8508
                        rpcPerms[idx] = &lnrpc.MacaroonPermission{
3✔
8509
                                Entity: perm.Entity,
3✔
8510
                                Action: perm.Action,
3✔
8511
                        }
3✔
8512
                }
3✔
8513
                permissionMap[uri] = &lnrpc.MacaroonPermissionList{
3✔
8514
                        Permissions: rpcPerms,
3✔
8515
                }
3✔
8516
        }
8517

8518
        return &lnrpc.ListPermissionsResponse{
3✔
8519
                MethodPermissions: permissionMap,
3✔
8520
        }, nil
3✔
8521
}
8522

8523
// CheckMacaroonPermissions checks the caveats and permissions of a macaroon.
8524
func (r *rpcServer) CheckMacaroonPermissions(ctx context.Context,
8525
        req *lnrpc.CheckMacPermRequest) (*lnrpc.CheckMacPermResponse, error) {
3✔
8526

3✔
8527
        // Turn grpc macaroon permission into bakery.Op for the server to
3✔
8528
        // process.
3✔
8529
        permissions := make([]bakery.Op, len(req.Permissions))
3✔
8530
        for idx, perm := range req.Permissions {
6✔
8531
                permissions[idx] = bakery.Op{
3✔
8532
                        Entity: perm.Entity,
3✔
8533
                        Action: perm.Action,
3✔
8534
                }
3✔
8535
        }
3✔
8536

8537
        err := r.macService.CheckMacAuth(
3✔
8538
                ctx, req.Macaroon, permissions, req.FullMethod,
3✔
8539
        )
3✔
8540
        if err != nil {
6✔
8541
                return nil, status.Error(codes.InvalidArgument, err.Error())
3✔
8542
        }
3✔
8543

8544
        return &lnrpc.CheckMacPermResponse{
3✔
8545
                Valid: true,
3✔
8546
        }, nil
3✔
8547
}
8548

8549
// FundingStateStep is an advanced funding related call that allows the caller
8550
// to either execute some preparatory steps for a funding workflow, or manually
8551
// progress a funding workflow. The primary way a funding flow is identified is
8552
// via its pending channel ID. As an example, this method can be used to
8553
// specify that we're expecting a funding flow for a particular pending channel
8554
// ID, for which we need to use specific parameters.  Alternatively, this can
8555
// be used to interactively drive PSBT signing for funding for partially
8556
// complete funding transactions.
8557
func (r *rpcServer) FundingStateStep(ctx context.Context,
8558
        in *lnrpc.FundingTransitionMsg) (*lnrpc.FundingStateStepResp, error) {
3✔
8559

3✔
8560
        var pendingChanID [32]byte
3✔
8561
        switch {
3✔
8562
        // If this is a message to register a new shim that is an external
8563
        // channel point, then we'll contact the wallet to register this new
8564
        // shim. A user will use this method to register a new channel funding
8565
        // workflow which has already been partially negotiated outside of the
8566
        // core protocol.
8567
        case in.GetShimRegister() != nil &&
8568
                in.GetShimRegister().GetChanPointShim() != nil:
3✔
8569

3✔
8570
                rpcShimIntent := in.GetShimRegister().GetChanPointShim()
3✔
8571

3✔
8572
                // Using the rpc shim as a template, we'll construct a new
3✔
8573
                // chanfunding.Assembler that is able to express proper
3✔
8574
                // formulation of this expected channel.
3✔
8575
                shimAssembler, err := newFundingShimAssembler(
3✔
8576
                        rpcShimIntent, false, r.server.cc.KeyRing,
3✔
8577
                )
3✔
8578
                if err != nil {
3✔
8579
                        return nil, err
×
8580
                }
×
8581
                req := &chanfunding.Request{
3✔
8582
                        RemoteAmt: btcutil.Amount(rpcShimIntent.Amt),
3✔
8583
                }
3✔
8584
                shimIntent, err := shimAssembler.ProvisionChannel(req)
3✔
8585
                if err != nil {
3✔
8586
                        return nil, err
×
8587
                }
×
8588

8589
                // Once we have the intent, we'll register it with the wallet.
8590
                // Once we receive an incoming funding request that uses this
8591
                // pending channel ID, then this shim will be dispatched in
8592
                // place of our regular funding workflow.
8593
                copy(pendingChanID[:], rpcShimIntent.PendingChanId)
3✔
8594
                err = r.server.cc.Wallet.RegisterFundingIntent(
3✔
8595
                        pendingChanID, shimIntent,
3✔
8596
                )
3✔
8597
                if err != nil {
6✔
8598
                        return nil, err
3✔
8599
                }
3✔
8600

8601
        // There is no need to register a PSBT shim before opening the channel,
8602
        // even though our RPC message structure allows for it. Inform the user
8603
        // by returning a proper error instead of just doing nothing.
8604
        case in.GetShimRegister() != nil &&
8605
                in.GetShimRegister().GetPsbtShim() != nil:
×
8606

×
8607
                return nil, fmt.Errorf("PSBT shim must only be sent when " +
×
8608
                        "opening a channel")
×
8609

8610
        // If this is a transition to cancel an existing shim, then we'll pass
8611
        // this message along to the wallet, informing it that the intent no
8612
        // longer needs to be considered and should be cleaned up.
8613
        case in.GetShimCancel() != nil:
×
8614
                rpcsLog.Debugf("Canceling funding shim for pending_id=%x",
×
8615
                        in.GetShimCancel().PendingChanId)
×
8616

×
8617
                copy(pendingChanID[:], in.GetShimCancel().PendingChanId)
×
8618
                err := r.server.cc.Wallet.CancelFundingIntent(pendingChanID)
×
8619
                if err != nil {
×
8620
                        return nil, err
×
8621
                }
×
8622

8623
        // If this is a transition to verify the PSBT for an existing shim,
8624
        // we'll do so and then store the verified PSBT for later so we can
8625
        // compare it to the final, signed one.
8626
        case in.GetPsbtVerify() != nil:
3✔
8627
                rpcsLog.Debugf("Verifying PSBT for pending_id=%x",
3✔
8628
                        in.GetPsbtVerify().PendingChanId)
3✔
8629

3✔
8630
                copy(pendingChanID[:], in.GetPsbtVerify().PendingChanId)
3✔
8631
                packet, err := psbt.NewFromRawBytes(
3✔
8632
                        bytes.NewReader(in.GetPsbtVerify().FundedPsbt), false,
3✔
8633
                )
3✔
8634
                if err != nil {
3✔
8635
                        return nil, fmt.Errorf("error parsing psbt: %w", err)
×
8636
                }
×
8637

8638
                err = r.server.cc.Wallet.PsbtFundingVerify(
3✔
8639
                        pendingChanID, packet, in.GetPsbtVerify().SkipFinalize,
3✔
8640
                )
3✔
8641
                if err != nil {
3✔
8642
                        return nil, err
×
8643
                }
×
8644

8645
        // If this is a transition to finalize the PSBT funding flow, we compare
8646
        // the final PSBT to the previously verified one and if nothing
8647
        // unexpected was changed, continue the channel opening process.
8648
        case in.GetPsbtFinalize() != nil:
3✔
8649
                msg := in.GetPsbtFinalize()
3✔
8650
                rpcsLog.Debugf("Finalizing PSBT for pending_id=%x",
3✔
8651
                        msg.PendingChanId)
3✔
8652

3✔
8653
                copy(pendingChanID[:], in.GetPsbtFinalize().PendingChanId)
3✔
8654

3✔
8655
                var (
3✔
8656
                        packet *psbt.Packet
3✔
8657
                        rawTx  *wire.MsgTx
3✔
8658
                        err    error
3✔
8659
                )
3✔
8660

3✔
8661
                // Either the signed PSBT or the raw transaction need to be set
3✔
8662
                // but not both at the same time.
3✔
8663
                switch {
3✔
8664
                case len(msg.SignedPsbt) > 0 && len(msg.FinalRawTx) > 0:
×
8665
                        return nil, fmt.Errorf("cannot set both signed PSBT " +
×
8666
                                "and final raw TX at the same time")
×
8667

8668
                case len(msg.SignedPsbt) > 0:
3✔
8669
                        packet, err = psbt.NewFromRawBytes(
3✔
8670
                                bytes.NewReader(in.GetPsbtFinalize().SignedPsbt),
3✔
8671
                                false,
3✔
8672
                        )
3✔
8673
                        if err != nil {
3✔
8674
                                return nil, fmt.Errorf("error parsing psbt: %w",
×
8675
                                        err)
×
8676
                        }
×
8677

8678
                case len(msg.FinalRawTx) > 0:
3✔
8679
                        rawTx = &wire.MsgTx{}
3✔
8680
                        err = rawTx.Deserialize(bytes.NewReader(msg.FinalRawTx))
3✔
8681
                        if err != nil {
3✔
8682
                                return nil, fmt.Errorf("error parsing final "+
×
8683
                                        "raw TX: %v", err)
×
8684
                        }
×
8685

8686
                default:
×
8687
                        return nil, fmt.Errorf("PSBT or raw transaction to " +
×
8688
                                "finalize missing")
×
8689
                }
8690

8691
                err = r.server.cc.Wallet.PsbtFundingFinalize(
3✔
8692
                        pendingChanID, packet, rawTx,
3✔
8693
                )
3✔
8694
                if err != nil {
3✔
8695
                        return nil, err
×
8696
                }
×
8697
        }
8698

8699
        // TODO(roasbeef): extend PendingChannels to also show shims
8700

8701
        // TODO(roasbeef): return resulting state? also add a method to query
8702
        // current state?
8703
        return &lnrpc.FundingStateStepResp{}, nil
3✔
8704
}
8705

8706
// RegisterRPCMiddleware adds a new gRPC middleware to the interceptor chain. A
8707
// gRPC middleware is software component external to lnd that aims to add
8708
// additional business logic to lnd by observing/intercepting/validating
8709
// incoming gRPC client requests and (if needed) replacing/overwriting outgoing
8710
// messages before they're sent to the client. When registering the middleware
8711
// must identify itself and indicate what custom macaroon caveats it wants to
8712
// be responsible for. Only requests that contain a macaroon with that specific
8713
// custom caveat are then sent to the middleware for inspection. As a security
8714
// measure, _no_ middleware can intercept requests made with _unencumbered_
8715
// macaroons!
8716
func (r *rpcServer) RegisterRPCMiddleware(
8717
        stream lnrpc.Lightning_RegisterRPCMiddlewareServer) error {
3✔
8718

3✔
8719
        // This is a security critical functionality and needs to be enabled
3✔
8720
        // specifically by the user.
3✔
8721
        if !r.cfg.RPCMiddleware.Enable {
3✔
8722
                return fmt.Errorf("RPC middleware not enabled in config")
×
8723
        }
×
8724

8725
        // When registering a middleware the first message being sent from the
8726
        // middleware must be a registration message containing its name and the
8727
        // custom caveat it wants to register for.
8728
        var (
3✔
8729
                registerChan     = make(chan *lnrpc.MiddlewareRegistration, 1)
3✔
8730
                registerDoneChan = make(chan struct{})
3✔
8731
                errChan          = make(chan error, 1)
3✔
8732
        )
3✔
8733
        ctxc, cancel := context.WithTimeout(
3✔
8734
                stream.Context(), r.cfg.RPCMiddleware.InterceptTimeout,
3✔
8735
        )
3✔
8736
        defer cancel()
3✔
8737

3✔
8738
        // Read the first message in a goroutine because the Recv method blocks
3✔
8739
        // until the message arrives.
3✔
8740
        go func() {
6✔
8741
                msg, err := stream.Recv()
3✔
8742
                if err != nil {
3✔
8743
                        errChan <- err
×
8744

×
8745
                        return
×
8746
                }
×
8747

8748
                registerChan <- msg.GetRegister()
3✔
8749
        }()
8750

8751
        // Wait for the initial message to arrive or time out if it takes too
8752
        // long.
8753
        var registerMsg *lnrpc.MiddlewareRegistration
3✔
8754
        select {
3✔
8755
        case registerMsg = <-registerChan:
3✔
8756
                if registerMsg == nil {
3✔
8757
                        return fmt.Errorf("invalid initial middleware " +
×
8758
                                "registration message")
×
8759
                }
×
8760

8761
        case err := <-errChan:
×
8762
                return fmt.Errorf("error receiving initial middleware "+
×
8763
                        "registration message: %v", err)
×
8764

8765
        case <-ctxc.Done():
×
8766
                return ctxc.Err()
×
8767

8768
        case <-r.quit:
×
8769
                return ErrServerShuttingDown
×
8770
        }
8771

8772
        // Make sure the registration is valid.
8773
        const nameMinLength = 5
3✔
8774
        if len(registerMsg.MiddlewareName) < nameMinLength {
6✔
8775
                return fmt.Errorf("invalid middleware name, use descriptive "+
3✔
8776
                        "name of at least %d characters", nameMinLength)
3✔
8777
        }
3✔
8778

8779
        readOnly := registerMsg.ReadOnlyMode
3✔
8780
        caveatName := registerMsg.CustomMacaroonCaveatName
3✔
8781
        switch {
3✔
8782
        case readOnly && len(caveatName) > 0:
3✔
8783
                return fmt.Errorf("cannot set read-only and custom caveat " +
3✔
8784
                        "name at the same time")
3✔
8785

8786
        case !readOnly && len(caveatName) < nameMinLength:
3✔
8787
                return fmt.Errorf("need to set either custom caveat name "+
3✔
8788
                        "of at least %d characters or read-only mode",
3✔
8789
                        nameMinLength)
3✔
8790
        }
8791

8792
        middleware := rpcperms.NewMiddlewareHandler(
3✔
8793
                registerMsg.MiddlewareName,
3✔
8794
                caveatName, readOnly, stream.Recv, stream.Send,
3✔
8795
                r.cfg.RPCMiddleware.InterceptTimeout,
3✔
8796
                r.cfg.ActiveNetParams.Params, r.quit,
3✔
8797
        )
3✔
8798

3✔
8799
        // Add the RPC middleware to the interceptor chain and defer its
3✔
8800
        // removal.
3✔
8801
        if err := r.interceptorChain.RegisterMiddleware(middleware); err != nil {
3✔
8802
                return fmt.Errorf("error registering middleware: %w", err)
×
8803
        }
×
8804
        defer r.interceptorChain.RemoveMiddleware(registerMsg.MiddlewareName)
3✔
8805

3✔
8806
        // Send a message to the client to indicate that the registration has
3✔
8807
        // successfully completed.
3✔
8808
        regCompleteMsg := &lnrpc.RPCMiddlewareRequest{
3✔
8809
                InterceptType: &lnrpc.RPCMiddlewareRequest_RegComplete{
3✔
8810
                        RegComplete: true,
3✔
8811
                },
3✔
8812
        }
3✔
8813

3✔
8814
        // Send the message in a goroutine because the Send method blocks until
3✔
8815
        // the message is read by the client.
3✔
8816
        go func() {
6✔
8817
                err := stream.Send(regCompleteMsg)
3✔
8818
                if err != nil {
3✔
8819
                        errChan <- err
×
8820
                        return
×
8821
                }
×
8822

8823
                close(registerDoneChan)
3✔
8824
        }()
8825

8826
        select {
3✔
8827
        case err := <-errChan:
×
8828
                return fmt.Errorf("error sending middleware registration "+
×
8829
                        "complete message: %v", err)
×
8830

8831
        case <-ctxc.Done():
×
8832
                return ctxc.Err()
×
8833

8834
        case <-r.quit:
×
8835
                return ErrServerShuttingDown
×
8836

8837
        case <-registerDoneChan:
3✔
8838
        }
8839

8840
        return middleware.Run()
3✔
8841
}
8842

8843
// SendCustomMessage sends a custom peer message.
8844
func (r *rpcServer) SendCustomMessage(_ context.Context,
8845
        req *lnrpc.SendCustomMessageRequest) (*lnrpc.SendCustomMessageResponse,
8846
        error) {
3✔
8847

3✔
8848
        peer, err := route.NewVertexFromBytes(req.Peer)
3✔
8849
        if err != nil {
3✔
8850
                return nil, err
×
8851
        }
×
8852

8853
        err = r.server.SendCustomMessage(
3✔
8854
                peer, lnwire.MessageType(req.Type), req.Data,
3✔
8855
        )
3✔
8856
        switch {
3✔
8857
        case errors.Is(err, ErrPeerNotConnected):
×
8858
                return nil, status.Error(codes.NotFound, err.Error())
×
8859
        case err != nil:
3✔
8860
                return nil, err
3✔
8861
        }
8862

8863
        return &lnrpc.SendCustomMessageResponse{
3✔
8864
                Status: "message sent successfully",
3✔
8865
        }, nil
3✔
8866
}
8867

8868
// SubscribeCustomMessages subscribes to a stream of incoming custom peer
8869
// messages.
8870
func (r *rpcServer) SubscribeCustomMessages(
8871
        _ *lnrpc.SubscribeCustomMessagesRequest,
8872
        server lnrpc.Lightning_SubscribeCustomMessagesServer) error {
3✔
8873

3✔
8874
        client, err := r.server.SubscribeCustomMessages()
3✔
8875
        if err != nil {
3✔
8876
                return err
×
8877
        }
×
8878
        defer client.Cancel()
3✔
8879

3✔
8880
        for {
6✔
8881
                select {
3✔
8882
                case <-client.Quit():
×
8883
                        return errors.New("shutdown")
×
8884

8885
                case <-server.Context().Done():
3✔
8886
                        return server.Context().Err()
3✔
8887

8888
                case update := <-client.Updates():
3✔
8889
                        customMsg := update.(*CustomMessage)
3✔
8890

3✔
8891
                        err := server.Send(&lnrpc.CustomMessage{
3✔
8892
                                Peer: customMsg.Peer[:],
3✔
8893
                                Data: customMsg.Msg.Data,
3✔
8894
                                Type: uint32(customMsg.Msg.Type),
3✔
8895
                        })
3✔
8896
                        if err != nil {
3✔
8897
                                return err
×
8898
                        }
×
8899
                }
8900
        }
8901
}
8902

8903
// ListAliases returns the set of all aliases we have ever allocated along with
8904
// their base SCIDs and possibly a separate confirmed SCID in the case of
8905
// zero-conf.
8906
func (r *rpcServer) ListAliases(_ context.Context,
8907
        _ *lnrpc.ListAliasesRequest) (*lnrpc.ListAliasesResponse, error) {
×
8908

×
8909
        // Fetch the map of all aliases.
×
8910
        mapAliases := r.server.aliasMgr.ListAliases()
×
8911

×
8912
        // Fill out the response. This does not include the zero-conf confirmed
×
8913
        // SCID. Doing so would require more database lookups, and it can be
×
8914
        // cross-referenced with the output of ListChannels/ClosedChannels.
×
8915
        resp := &lnrpc.ListAliasesResponse{
×
8916
                AliasMaps: make([]*lnrpc.AliasMap, 0),
×
8917
        }
×
8918

×
8919
        // Now we need to parse the created mappings into an rpc response.
×
8920
        resp.AliasMaps = lnrpc.MarshalAliasMap(mapAliases)
×
8921

×
8922
        return resp, nil
×
8923
}
×
8924

8925
// rpcInitiator returns the correct lnrpc initiator for channels where we have
8926
// a record of the opening channel.
8927
func rpcInitiator(isInitiator bool) lnrpc.Initiator {
3✔
8928
        if isInitiator {
6✔
8929
                return lnrpc.Initiator_INITIATOR_LOCAL
3✔
8930
        }
3✔
8931

8932
        return lnrpc.Initiator_INITIATOR_REMOTE
3✔
8933
}
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