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

lightningnetwork / lnd / 19338576814

13 Nov 2025 04:31PM UTC coverage: 65.209% (-0.01%) from 65.219%
19338576814

Pull #10367

github

web-flow
Merge ade491779 into f6005ed35
Pull Request #10367: multi: rename experimental endorsement signal to accountable

65 of 85 new or added lines in 11 files covered. (76.47%)

1775 existing lines in 24 files now uncovered.

137557 of 210947 relevant lines covered (65.21%)

20763.21 hits per line

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

73.8
/funding/manager.go
1
package funding
2

3
import (
4
        "bytes"
5
        "encoding/binary"
6
        "errors"
7
        "fmt"
8
        "io"
9
        "sync"
10
        "sync/atomic"
11
        "time"
12

13
        "github.com/btcsuite/btcd/blockchain"
14
        "github.com/btcsuite/btcd/btcec/v2"
15
        "github.com/btcsuite/btcd/btcec/v2/ecdsa"
16
        "github.com/btcsuite/btcd/btcec/v2/schnorr/musig2"
17
        "github.com/btcsuite/btcd/btcutil"
18
        "github.com/btcsuite/btcd/chaincfg/chainhash"
19
        "github.com/btcsuite/btcd/txscript"
20
        "github.com/btcsuite/btcd/wire"
21
        "github.com/lightningnetwork/lnd/chainntnfs"
22
        "github.com/lightningnetwork/lnd/chanacceptor"
23
        "github.com/lightningnetwork/lnd/channeldb"
24
        "github.com/lightningnetwork/lnd/discovery"
25
        "github.com/lightningnetwork/lnd/fn/v2"
26
        "github.com/lightningnetwork/lnd/graph"
27
        "github.com/lightningnetwork/lnd/graph/db/models"
28
        "github.com/lightningnetwork/lnd/input"
29
        "github.com/lightningnetwork/lnd/keychain"
30
        "github.com/lightningnetwork/lnd/labels"
31
        "github.com/lightningnetwork/lnd/lncfg"
32
        "github.com/lightningnetwork/lnd/lnpeer"
33
        "github.com/lightningnetwork/lnd/lnrpc"
34
        "github.com/lightningnetwork/lnd/lnutils"
35
        "github.com/lightningnetwork/lnd/lnwallet"
36
        "github.com/lightningnetwork/lnd/lnwallet/chainfee"
37
        "github.com/lightningnetwork/lnd/lnwallet/chanfunding"
38
        "github.com/lightningnetwork/lnd/lnwire"
39
        "golang.org/x/crypto/salsa20"
40
)
41

42
var (
43
        // byteOrder defines the endian-ness we use for encoding to and from
44
        // buffers.
45
        byteOrder = binary.BigEndian
46

47
        // checkPeerChannelReadyInterval is used when we are waiting for the
48
        // peer to send us ChannelReady. We will check every 1 second to see
49
        // if the message is received.
50
        //
51
        // NOTE: for itest, this value is changed to 10ms.
52
        checkPeerChannelReadyInterval = 1 * time.Second
53

54
        // errNoLocalNonce is returned when a local nonce is not found in the
55
        // expected TLV.
56
        errNoLocalNonce = fmt.Errorf("local nonce not found")
57

58
        // errNoPartialSig is returned when a partial sig is not found in the
59
        // expected TLV.
60
        errNoPartialSig = fmt.Errorf("partial sig not found")
61
)
62

63
// WriteOutpoint writes an outpoint to an io.Writer. This is not the same as
64
// the channeldb variant as this uses WriteVarBytes for the Hash.
65
func WriteOutpoint(w io.Writer, o *wire.OutPoint) error {
371✔
66
        scratch := make([]byte, 4)
371✔
67

371✔
68
        if err := wire.WriteVarBytes(w, 0, o.Hash[:]); err != nil {
371✔
69
                return err
×
70
        }
×
71

72
        byteOrder.PutUint32(scratch, o.Index)
371✔
73
        _, err := w.Write(scratch)
371✔
74
        return err
371✔
75
}
76

77
const (
78
        // MinBtcRemoteDelay is the minimum CSV delay we will require the remote
79
        // to use for its commitment transaction.
80
        MinBtcRemoteDelay uint16 = 144
81

82
        // MaxBtcRemoteDelay is the maximum CSV delay we will require the remote
83
        // to use for its commitment transaction.
84
        MaxBtcRemoteDelay uint16 = 2016
85

86
        // MinChanFundingSize is the smallest channel that we'll allow to be
87
        // created over the RPC interface.
88
        MinChanFundingSize = btcutil.Amount(20000)
89

90
        // MaxBtcFundingAmount is a soft-limit of the maximum channel size
91
        // currently accepted on the Bitcoin chain within the Lightning
92
        // Protocol. This limit is defined in BOLT-0002, and serves as an
93
        // initial precautionary limit while implementations are battle tested
94
        // in the real world.
95
        MaxBtcFundingAmount = btcutil.Amount(1<<24) - 1
96

97
        // MaxBtcFundingAmountWumbo is a soft-limit on the maximum size of wumbo
98
        // channels. This limit is 10 BTC and is the only thing standing between
99
        // you and limitless channel size (apart from 21 million cap).
100
        MaxBtcFundingAmountWumbo = btcutil.Amount(1000000000)
101

102
        msgBufferSize = 50
103

104
        // pendingChansLimit is the maximum number of pending channels that we
105
        // can have. After this point, pending channel opens will start to be
106
        // rejected.
107
        pendingChansLimit = 50
108
)
109

110
var (
111
        // ErrFundingManagerShuttingDown is an error returned when attempting to
112
        // process a funding request/message but the funding manager has already
113
        // been signaled to shut down.
114
        ErrFundingManagerShuttingDown = errors.New("funding manager shutting " +
115
                "down")
116

117
        // ErrConfirmationTimeout is an error returned when we as a responder
118
        // are waiting for a funding transaction to confirm, but too many
119
        // blocks pass without confirmation.
120
        ErrConfirmationTimeout = errors.New("timeout waiting for funding " +
121
                "confirmation")
122

123
        // errUpfrontShutdownScriptNotSupported is returned if an upfront
124
        // shutdown script is set for a peer that does not support the feature
125
        // bit.
126
        errUpfrontShutdownScriptNotSupported = errors.New("peer does not " +
127
                "support option upfront shutdown script")
128

129
        zeroID [32]byte
130
)
131

132
// reservationWithCtx encapsulates a pending channel reservation. This wrapper
133
// struct is used internally within the funding manager to track and progress
134
// the funding workflow initiated by incoming/outgoing methods from the target
135
// peer. Additionally, this struct houses a response and error channel which is
136
// used to respond to the caller in the case a channel workflow is initiated
137
// via a local signal such as RPC.
138
//
139
// TODO(roasbeef): actually use the context package
140
//   - deadlines, etc.
141
type reservationWithCtx struct {
142
        reservation *lnwallet.ChannelReservation
143
        peer        lnpeer.Peer
144

145
        chanAmt btcutil.Amount
146

147
        // forwardingPolicy is the policy provided by the initFundingMsg.
148
        forwardingPolicy models.ForwardingPolicy
149

150
        // Constraints we require for the remote.
151
        remoteCsvDelay    uint16
152
        remoteMinHtlc     lnwire.MilliSatoshi
153
        remoteMaxValue    lnwire.MilliSatoshi
154
        remoteMaxHtlcs    uint16
155
        remoteChanReserve btcutil.Amount
156

157
        // maxLocalCsv is the maximum csv we will accept from the remote.
158
        maxLocalCsv uint16
159

160
        // channelType is the explicit channel type proposed by the initiator of
161
        // the channel.
162
        channelType *lnwire.ChannelType
163

164
        updateMtx   sync.RWMutex
165
        lastUpdated time.Time
166

167
        updates chan *lnrpc.OpenStatusUpdate
168
        err     chan error
169
}
170

171
// isLocked checks the reservation's timestamp to determine whether it is
172
// locked.
173
func (r *reservationWithCtx) isLocked() bool {
6✔
174
        r.updateMtx.RLock()
6✔
175
        defer r.updateMtx.RUnlock()
6✔
176

6✔
177
        // The time zero value represents a locked reservation.
6✔
178
        return r.lastUpdated.IsZero()
6✔
179
}
6✔
180

181
// updateTimestamp updates the reservation's timestamp with the current time.
182
func (r *reservationWithCtx) updateTimestamp() {
140✔
183
        r.updateMtx.Lock()
140✔
184
        defer r.updateMtx.Unlock()
140✔
185

140✔
186
        r.lastUpdated = time.Now()
140✔
187
}
140✔
188

189
// InitFundingMsg is sent by an outside subsystem to the funding manager in
190
// order to kick off a funding workflow with a specified target peer. The
191
// original request which defines the parameters of the funding workflow are
192
// embedded within this message giving the funding manager full context w.r.t
193
// the workflow.
194
type InitFundingMsg struct {
195
        // Peer is the peer that we want to open a channel to.
196
        Peer lnpeer.Peer
197

198
        // TargetPubkey is the public key of the peer.
199
        TargetPubkey *btcec.PublicKey
200

201
        // ChainHash is the target genesis hash for this channel.
202
        ChainHash chainhash.Hash
203

204
        // SubtractFees set to true means that fees will be subtracted
205
        // from the LocalFundingAmt.
206
        SubtractFees bool
207

208
        // LocalFundingAmt is the size of the channel.
209
        LocalFundingAmt btcutil.Amount
210

211
        // BaseFee is the base fee charged for routing payments regardless of
212
        // the number of milli-satoshis sent.
213
        BaseFee *uint64
214

215
        // FeeRate is the fee rate in ppm (parts per million) that will be
216
        // charged proportionally based on the value of each forwarded HTLC, the
217
        // lowest possible rate is 0 with a granularity of 0.000001
218
        // (millionths).
219
        FeeRate *uint64
220

221
        // PushAmt is the amount pushed to the counterparty.
222
        PushAmt lnwire.MilliSatoshi
223

224
        // FundingFeePerKw is the fee for the funding transaction.
225
        FundingFeePerKw chainfee.SatPerKWeight
226

227
        // Private determines whether or not this channel will be private.
228
        Private bool
229

230
        // MinHtlcIn is the minimum incoming HTLC that we accept.
231
        MinHtlcIn lnwire.MilliSatoshi
232

233
        // RemoteCsvDelay is the CSV delay we require for the remote peer.
234
        RemoteCsvDelay uint16
235

236
        // RemoteChanReserve is the channel reserve we required for the remote
237
        // peer.
238
        RemoteChanReserve btcutil.Amount
239

240
        // MinConfs indicates the minimum number of confirmations that each
241
        // output selected to fund the channel should satisfy.
242
        MinConfs int32
243

244
        // ShutdownScript is an optional upfront shutdown script for the
245
        // channel. This value is optional, so may be nil.
246
        ShutdownScript lnwire.DeliveryAddress
247

248
        // MaxValueInFlight is the maximum amount of coins in MilliSatoshi
249
        // that can be pending within the channel. It only applies to the
250
        // remote party.
251
        MaxValueInFlight lnwire.MilliSatoshi
252

253
        // MaxHtlcs is the maximum number of HTLCs that the remote peer
254
        // can offer us.
255
        MaxHtlcs uint16
256

257
        // MaxLocalCsv is the maximum local csv delay we will accept from our
258
        // peer.
259
        MaxLocalCsv uint16
260

261
        // FundUpToMaxAmt is the maximum amount to try to commit to. If set, the
262
        // MinFundAmt field denotes the acceptable minimum amount to commit to,
263
        // while trying to commit as many coins as possible up to this value.
264
        FundUpToMaxAmt btcutil.Amount
265

266
        // MinFundAmt must be set iff FundUpToMaxAmt is set. It denotes the
267
        // minimum amount to commit to.
268
        MinFundAmt btcutil.Amount
269

270
        // Outpoints is a list of client-selected outpoints that should be used
271
        // for funding a channel. If LocalFundingAmt is specified then this
272
        // amount is allocated from the sum of outpoints towards funding. If
273
        // the FundUpToMaxAmt is specified the entirety of selected funds is
274
        // allocated towards channel funding.
275
        Outpoints []wire.OutPoint
276

277
        // ChanFunder is an optional channel funder that allows the caller to
278
        // control exactly how the channel funding is carried out. If not
279
        // specified, then the default chanfunding.WalletAssembler will be
280
        // used.
281
        ChanFunder chanfunding.Assembler
282

283
        // PendingChanID is not all zeroes (the default value), then this will
284
        // be the pending channel ID used for the funding flow within the wire
285
        // protocol.
286
        PendingChanID PendingChanID
287

288
        // ChannelType allows the caller to use an explicit channel type for the
289
        // funding negotiation. This type will only be observed if BOTH sides
290
        // support explicit channel type negotiation.
291
        ChannelType *lnwire.ChannelType
292

293
        // Memo is any arbitrary information we wish to store locally about the
294
        // channel that will be useful to our future selves.
295
        Memo []byte
296

297
        // Updates is a channel which updates to the opening status of the
298
        // channel are sent on.
299
        Updates chan *lnrpc.OpenStatusUpdate
300

301
        // Err is a channel which errors encountered during the funding flow are
302
        // sent on.
303
        Err chan error
304
}
305

306
// fundingMsg is sent by the ProcessFundingMsg function and packages a
307
// funding-specific lnwire.Message along with the lnpeer.Peer that sent it.
308
type fundingMsg struct {
309
        msg  lnwire.Message
310
        peer lnpeer.Peer
311
}
312

313
// pendingChannels is a map instantiated per-peer which tracks all active
314
// pending single funded channels indexed by their pending channel identifier,
315
// which is a set of 32-bytes generated via a CSPRNG.
316
type pendingChannels map[PendingChanID]*reservationWithCtx
317

318
// serializedPubKey is used within the FundingManager's activeReservations list
319
// to identify the nodes with which the FundingManager is actively working to
320
// initiate new channels.
321
type serializedPubKey [33]byte
322

323
// newSerializedKey creates a new serialized public key from an instance of a
324
// live pubkey object.
325
func newSerializedKey(pubKey *btcec.PublicKey) serializedPubKey {
392✔
326
        var s serializedPubKey
392✔
327
        copy(s[:], pubKey.SerializeCompressed())
392✔
328
        return s
392✔
329
}
392✔
330

331
// DevConfig specifies configs used for integration test only.
332
type DevConfig struct {
333
        // ProcessChannelReadyWait is the duration to sleep before processing
334
        // remote node's channel ready message once the channel as been marked
335
        // as `channelReadySent`.
336
        ProcessChannelReadyWait time.Duration
337

338
        // MaxWaitNumBlocksFundingConf is the maximum number of blocks to wait
339
        // for the funding transaction to be confirmed before forgetting
340
        // channels that aren't initiated by us.
341
        MaxWaitNumBlocksFundingConf uint32
342
}
343

344
// Config defines the configuration for the FundingManager. All elements
345
// within the configuration MUST be non-nil for the FundingManager to carry out
346
// its duties.
347
type Config struct {
348
        // Dev specifies config values used in integration test. For
349
        // production, this config will always be an empty struct.
350
        Dev *DevConfig
351

352
        // NoWumboChans indicates if we're to reject all incoming wumbo channel
353
        // requests, and also reject all outgoing wumbo channel requests.
354
        NoWumboChans bool
355

356
        // IDKey is the PublicKey that is used to identify this node within the
357
        // Lightning Network.
358
        IDKey *btcec.PublicKey
359

360
        // IDKeyLoc is the locator for the key that is used to identify this
361
        // node within the LightningNetwork.
362
        IDKeyLoc keychain.KeyLocator
363

364
        // Wallet handles the parts of the funding process that involves moving
365
        // funds from on-chain transaction outputs into Lightning channels.
366
        Wallet *lnwallet.LightningWallet
367

368
        // PublishTransaction facilitates the process of broadcasting a
369
        // transaction to the network.
370
        PublishTransaction func(*wire.MsgTx, string) error
371

372
        // UpdateLabel updates the label that a transaction has in our wallet,
373
        // overwriting any existing labels.
374
        UpdateLabel func(chainhash.Hash, string) error
375

376
        // FeeEstimator calculates appropriate fee rates based on historical
377
        // transaction information.
378
        FeeEstimator chainfee.Estimator
379

380
        // Notifier is used by the FundingManager to determine when the
381
        // channel's funding transaction has been confirmed on the blockchain
382
        // so that the channel creation process can be completed.
383
        Notifier chainntnfs.ChainNotifier
384

385
        // ChannelDB is the database that keeps track of all channel state.
386
        ChannelDB *channeldb.ChannelStateDB
387

388
        // SignMessage signs an arbitrary message with a given public key. The
389
        // actual digest signed is the double sha-256 of the message. In the
390
        // case that the private key corresponding to the passed public key
391
        // cannot be located, then an error is returned.
392
        //
393
        // TODO(roasbeef): should instead pass on this responsibility to a
394
        // distinct sub-system?
395
        SignMessage func(keyLoc keychain.KeyLocator,
396
                msg []byte, doubleHash bool) (*ecdsa.Signature, error)
397

398
        // CurrentNodeAnnouncement should return the latest, fully signed node
399
        // announcement from the backing Lightning Network node with a fresh
400
        // timestamp.
401
        CurrentNodeAnnouncement func() (lnwire.NodeAnnouncement1, error)
402

403
        // SendAnnouncement is used by the FundingManager to send announcement
404
        // messages to the Gossiper to possibly broadcast to the greater
405
        // network. A set of optional message fields can be provided to populate
406
        // any information within the graph that is not included in the gossip
407
        // message.
408
        SendAnnouncement func(msg lnwire.Message,
409
                optionalFields ...discovery.OptionalMsgField) chan error
410

411
        // NotifyWhenOnline allows the FundingManager to register with a
412
        // subsystem that will notify it when the peer comes online. This is
413
        // used when sending the channelReady message, since it MUST be
414
        // delivered after the funding transaction is confirmed.
415
        //
416
        // NOTE: The peerChan channel must be buffered.
417
        NotifyWhenOnline func(peer [33]byte, peerChan chan<- lnpeer.Peer)
418

419
        // FindChannel queries the database for the channel with the given
420
        // channel ID. Providing the node's public key is an optimization that
421
        // prevents deserializing and scanning through all possible channels.
422
        FindChannel func(node *btcec.PublicKey,
423
                chanID lnwire.ChannelID) (*channeldb.OpenChannel, error)
424

425
        // TempChanIDSeed is a cryptographically random string of bytes that's
426
        // used as a seed to generate pending channel ID's.
427
        TempChanIDSeed [32]byte
428

429
        // DefaultRoutingPolicy is the default routing policy used when
430
        // initially announcing channels.
431
        DefaultRoutingPolicy models.ForwardingPolicy
432

433
        // DefaultMinHtlcIn is the default minimum incoming htlc value that is
434
        // set as a channel parameter.
435
        DefaultMinHtlcIn lnwire.MilliSatoshi
436

437
        // NumRequiredConfs is a function closure that helps the funding
438
        // manager decide how many confirmations it should require for a
439
        // channel extended to it. The function is able to take into account
440
        // the amount of the channel, and any funds we'll be pushed in the
441
        // process to determine how many confirmations we'll require.
442
        NumRequiredConfs func(btcutil.Amount, lnwire.MilliSatoshi) uint16
443

444
        // RequiredRemoteDelay is a function that maps the total amount in a
445
        // proposed channel to the CSV delay that we'll require for the remote
446
        // party. Naturally a larger channel should require a higher CSV delay
447
        // in order to give us more time to claim funds in the case of a
448
        // contract breach.
449
        RequiredRemoteDelay func(btcutil.Amount) uint16
450

451
        // RequiredRemoteChanReserve is a function closure that, given the
452
        // channel capacity and dust limit, will return an appropriate amount
453
        // for the remote peer's required channel reserve that is to be adhered
454
        // to at all times.
455
        RequiredRemoteChanReserve func(capacity,
456
                dustLimit btcutil.Amount) btcutil.Amount
457

458
        // RequiredRemoteMaxValue is a function closure that, given the channel
459
        // capacity, returns the amount of MilliSatoshis that our remote peer
460
        // can have in total outstanding HTLCs with us.
461
        RequiredRemoteMaxValue func(btcutil.Amount) lnwire.MilliSatoshi
462

463
        // RequiredRemoteMaxHTLCs is a function closure that, given the channel
464
        // capacity, returns the number of maximum HTLCs the remote peer can
465
        // offer us.
466
        RequiredRemoteMaxHTLCs func(btcutil.Amount) uint16
467

468
        // WatchNewChannel is to be called once a new channel enters the final
469
        // funding stage: waiting for on-chain confirmation. This method sends
470
        // the channel to the ChainArbitrator so it can watch for any on-chain
471
        // events related to the channel. We also provide the public key of the
472
        // node we're establishing a channel with for reconnection purposes.
473
        WatchNewChannel func(*channeldb.OpenChannel, *btcec.PublicKey) error
474

475
        // ReportShortChanID allows the funding manager to report the confirmed
476
        // short channel ID of a formerly pending zero-conf channel to outside
477
        // sub-systems.
478
        ReportShortChanID func(wire.OutPoint) error
479

480
        // ZombieSweeperInterval is the periodic time interval in which the
481
        // zombie sweeper is run.
482
        ZombieSweeperInterval time.Duration
483

484
        // ReservationTimeout is the length of idle time that must pass before
485
        // a reservation is considered a zombie.
486
        ReservationTimeout time.Duration
487

488
        // MinChanSize is the smallest channel size that we'll accept as an
489
        // inbound channel. We have such a parameter, as otherwise, nodes could
490
        // flood us with very small channels that would never really be usable
491
        // due to fees.
492
        MinChanSize btcutil.Amount
493

494
        // MaxChanSize is the largest channel size that we'll accept as an
495
        // inbound channel. We have such a parameter, so that you may decide how
496
        // WUMBO you would like your channel.
497
        MaxChanSize btcutil.Amount
498

499
        // MaxPendingChannels is the maximum number of pending channels we
500
        // allow for each peer.
501
        MaxPendingChannels int
502

503
        // RejectPush is set true if the fundingmanager should reject any
504
        // incoming channels having a non-zero push amount.
505
        RejectPush bool
506

507
        // MaxLocalCSVDelay is the maximum csv delay we will allow for our
508
        // commit output. Channels that exceed this value will be failed.
509
        MaxLocalCSVDelay uint16
510

511
        // NotifyOpenChannelEvent informs the ChannelNotifier when channels
512
        // transition from pending open to open.
513
        NotifyOpenChannelEvent func(wire.OutPoint, *btcec.PublicKey)
514

515
        // OpenChannelPredicate is a predicate on the lnwire.OpenChannel message
516
        // and on the requesting node's public key that returns a bool which
517
        // tells the funding manager whether or not to accept the channel.
518
        OpenChannelPredicate chanacceptor.ChannelAcceptor
519

520
        // NotifyPendingOpenChannelEvent informs the ChannelNotifier when
521
        // channels enter a pending state.
522
        NotifyPendingOpenChannelEvent func(wire.OutPoint,
523
                *channeldb.OpenChannel, *btcec.PublicKey)
524

525
        // NotifyFundingTimeout informs the ChannelNotifier when a pending-open
526
        // channel times out because the funding transaction hasn't confirmed.
527
        // This is only called for the fundee and only if the channel is
528
        // zero-conf.
529
        NotifyFundingTimeout func(wire.OutPoint, *btcec.PublicKey)
530

531
        // EnableUpfrontShutdown specifies whether the upfront shutdown script
532
        // is enabled.
533
        EnableUpfrontShutdown bool
534

535
        // MaxAnchorsCommitFeeRate is the max commitment fee rate we'll use as
536
        // the initiator for channels of the anchor type.
537
        MaxAnchorsCommitFeeRate chainfee.SatPerKWeight
538

539
        // DeleteAliasEdge allows the Manager to delete an alias channel edge
540
        // from the graph. It also returns our local to-be-deleted policy.
541
        DeleteAliasEdge func(scid lnwire.ShortChannelID) (
542
                *models.ChannelEdgePolicy, error)
543

544
        // AliasManager is an implementation of the aliasHandler interface that
545
        // abstracts away the handling of many alias functions.
546
        AliasManager aliasHandler
547

548
        // IsSweeperOutpoint queries the sweeper store for successfully
549
        // published sweeps. This is useful to decide for the internal wallet
550
        // backed funding flow to not use utxos still being swept by the sweeper
551
        // subsystem.
552
        IsSweeperOutpoint func(wire.OutPoint) bool
553

554
        // AuxLeafStore is an optional store that can be used to store auxiliary
555
        // leaves for certain custom channel types.
556
        AuxLeafStore fn.Option[lnwallet.AuxLeafStore]
557

558
        // AuxFundingController is an optional controller that can be used to
559
        // modify the way we handle certain custom channel types. It's also
560
        // able to automatically handle new custom protocol messages related to
561
        // the funding process.
562
        AuxFundingController fn.Option[AuxFundingController]
563

564
        // AuxSigner is an optional signer that can be used to sign auxiliary
565
        // leaves for certain custom channel types.
566
        AuxSigner fn.Option[lnwallet.AuxSigner]
567

568
        // AuxResolver is an optional interface that can be used to modify the
569
        // way contracts are resolved.
570
        AuxResolver fn.Option[lnwallet.AuxContractResolver]
571

572
        // AuxChannelNegotiator is an optional interface that allows aux channel
573
        // implementations to inject and process custom records over channel
574
        // related wire messages.
575
        AuxChannelNegotiator fn.Option[lnwallet.AuxChannelNegotiator]
576
}
577

578
// Manager acts as an orchestrator/bridge between the wallet's
579
// 'ChannelReservation' workflow, and the wire protocol's funding initiation
580
// messages. Any requests to initiate the funding workflow for a channel,
581
// either kicked-off locally or remotely are handled by the funding manager.
582
// Once a channel's funding workflow has been completed, any local callers, the
583
// local peer, and possibly the remote peer are notified of the completion of
584
// the channel workflow. Additionally, any temporary or permanent access
585
// controls between the wallet and remote peers are enforced via the funding
586
// manager.
587
type Manager struct {
588
        started sync.Once
589
        stopped sync.Once
590

591
        // cfg is a copy of the configuration struct that the FundingManager
592
        // was initialized with.
593
        cfg *Config
594

595
        // chanIDKey is a cryptographically random key that's used to generate
596
        // temporary channel ID's.
597
        chanIDKey [32]byte
598

599
        // chanIDNonce is a nonce that's incremented for each new funding
600
        // reservation created.
601
        chanIDNonce atomic.Uint64
602

603
        // nonceMtx is a mutex that guards the pendingMusigNonces.
604
        nonceMtx sync.RWMutex
605

606
        // pendingMusigNonces is used to store the musig2 nonce we generate to
607
        // send funding locked until we receive a funding locked message from
608
        // the remote party. We'll use this to keep track of the nonce we
609
        // generated, so we send the local+remote nonces to the peer state
610
        // machine.
611
        //
612
        // NOTE: This map is protected by the nonceMtx above.
613
        //
614
        // TODO(roasbeef): replace w/ generic concurrent map
615
        pendingMusigNonces map[lnwire.ChannelID]*musig2.Nonces
616

617
        // activeReservations is a map which houses the state of all pending
618
        // funding workflows.
619
        activeReservations map[serializedPubKey]pendingChannels
620

621
        // signedReservations is a utility map that maps the permanent channel
622
        // ID of a funding reservation to its temporary channel ID. This is
623
        // required as mid funding flow, we switch to referencing the channel
624
        // by its full channel ID once the commitment transactions have been
625
        // signed by both parties.
626
        signedReservations map[lnwire.ChannelID]PendingChanID
627

628
        // resMtx guards both of the maps above to ensure that all access is
629
        // goroutine safe.
630
        resMtx sync.RWMutex
631

632
        // fundingMsgs is a channel that relays fundingMsg structs from
633
        // external sub-systems using the ProcessFundingMsg call.
634
        fundingMsgs chan *fundingMsg
635

636
        // fundingRequests is a channel used to receive channel initiation
637
        // requests from a local subsystem within the daemon.
638
        fundingRequests chan *InitFundingMsg
639

640
        localDiscoverySignals *lnutils.SyncMap[lnwire.ChannelID, chan struct{}]
641

642
        handleChannelReadyBarriers *lnutils.SyncMap[lnwire.ChannelID, struct{}]
643

644
        quit chan struct{}
645
        wg   sync.WaitGroup
646
}
647

648
// channelOpeningState represents the different states a channel can be in
649
// between the funding transaction has been confirmed and the channel is
650
// announced to the network and ready to be used.
651
type channelOpeningState uint8
652

653
const (
654
        // markedOpen is the opening state of a channel if the funding
655
        // transaction is confirmed on-chain, but channelReady is not yet
656
        // successfully sent to the other peer.
657
        markedOpen channelOpeningState = iota
658

659
        // channelReadySent is the opening state of a channel if the
660
        // channelReady message has successfully been sent to the other peer,
661
        // but we still haven't announced the channel to the network.
662
        channelReadySent
663

664
        // addedToGraph is the opening state of a channel if the channel has
665
        // been successfully added to the graph immediately after the
666
        // channelReady message has been sent, but we still haven't announced
667
        // the channel to the network.
668
        addedToGraph
669
)
670

671
func (c channelOpeningState) String() string {
672
        switch c {
673
        case markedOpen:
674
                return "markedOpen"
675
        case channelReadySent:
3✔
676
                return "channelReadySent"
3✔
677
        case addedToGraph:
3✔
678
                return "addedToGraph"
3✔
679
        default:
3✔
680
                return "unknown"
3✔
681
        }
3✔
682
}
3✔
UNCOV
683

×
UNCOV
684
// NewFundingManager creates and initializes a new instance of the
×
685
// fundingManager.
686
func NewFundingManager(cfg Config) (*Manager, error) {
687
        return &Manager{
688
                cfg:       &cfg,
689
                chanIDKey: cfg.TempChanIDSeed,
690
                activeReservations: make(
112✔
691
                        map[serializedPubKey]pendingChannels,
112✔
692
                ),
112✔
693
                signedReservations: make(
112✔
694
                        map[lnwire.ChannelID][32]byte,
112✔
695
                ),
112✔
696
                fundingMsgs: make(
112✔
697
                        chan *fundingMsg, msgBufferSize,
112✔
698
                ),
112✔
699
                fundingRequests: make(
112✔
700
                        chan *InitFundingMsg, msgBufferSize,
112✔
701
                ),
112✔
702
                localDiscoverySignals: &lnutils.SyncMap[
112✔
703
                        lnwire.ChannelID, chan struct{},
112✔
704
                ]{},
112✔
705
                handleChannelReadyBarriers: &lnutils.SyncMap[
112✔
706
                        lnwire.ChannelID, struct{},
112✔
707
                ]{},
112✔
708
                pendingMusigNonces: make(
112✔
709
                        map[lnwire.ChannelID]*musig2.Nonces,
112✔
710
                ),
112✔
711
                quit: make(chan struct{}),
112✔
712
        }, nil
112✔
713
}
112✔
714

112✔
715
// Start launches all helper goroutines required for handling requests sent
112✔
716
// to the funding manager.
112✔
717
func (f *Manager) Start() error {
112✔
718
        var err error
719
        f.started.Do(func() {
720
                log.Info("Funding manager starting")
721
                err = f.start()
112✔
722
        })
112✔
723
        return err
224✔
724
}
112✔
725

112✔
726
func (f *Manager) start() error {
112✔
727
        // Upon restart, the Funding Manager will check the database to load any
112✔
728
        // channels that were  waiting for their funding transactions to be
729
        // confirmed on the blockchain at the time when the daemon last went
730
        // down.
112✔
731
        // TODO(roasbeef): store height that funding finished?
112✔
732
        //  * would then replace call below
112✔
733
        allChannels, err := f.cfg.ChannelDB.FetchAllChannels()
112✔
734
        if err != nil {
112✔
735
                return err
112✔
736
        }
112✔
737

112✔
738
        for _, channel := range allChannels {
112✔
UNCOV
739
                chanID := lnwire.NewChanIDFromOutPoint(channel.FundingOutpoint)
×
UNCOV
740

×
741
                // For any channels that were in a pending state when the
742
                // daemon was last connected, the Funding Manager will
124✔
743
                // re-initialize the channel barriers, and republish the
12✔
744
                // funding transaction if we're the initiator.
12✔
745
                if channel.IsPending {
12✔
746
                        log.Tracef("Loading pending ChannelPoint(%v), "+
12✔
747
                                "creating chan barrier",
12✔
748
                                channel.FundingOutpoint)
12✔
749

16✔
750
                        f.localDiscoverySignals.Store(
4✔
751
                                chanID, make(chan struct{}),
4✔
752
                        )
4✔
753

4✔
754
                        // Rebroadcast the funding transaction for any pending
4✔
755
                        // channel that we initiated. No error will be returned
4✔
756
                        // if the transaction already has been broadcast.
4✔
757
                        chanType := channel.ChanType
4✔
758
                        if chanType.IsSingleFunder() &&
4✔
759
                                chanType.HasFundingTx() &&
4✔
760
                                channel.IsInitiator {
4✔
761

4✔
762
                                f.rebroadcastFundingTx(channel)
4✔
763
                        }
4✔
764
                } else if channel.ChanType.IsSingleFunder() &&
8✔
765
                        channel.ChanType.HasFundingTx() &&
4✔
766
                        channel.IsZeroConf() && channel.IsInitiator &&
4✔
767
                        !channel.ZeroConfConfirmed() {
4✔
768

11✔
769
                        // Rebroadcast the funding transaction for unconfirmed
11✔
770
                        // zero-conf channels if we have the funding tx and are
11✔
771
                        // also the initiator.
13✔
772
                        f.rebroadcastFundingTx(channel)
2✔
773
                }
2✔
774

2✔
775
                // We will restart the funding state machine for all channels,
2✔
776
                // which will wait for the channel's funding transaction to be
2✔
777
                // confirmed on the blockchain, and transmit the messages
2✔
778
                // necessary for the channel to be operational.
779
                f.wg.Add(1)
780
                go f.advanceFundingState(channel, chanID, nil)
781
        }
782

783
        f.wg.Add(1) // TODO(roasbeef): tune
12✔
784
        go f.reservationCoordinator()
12✔
785

786
        return nil
787
}
112✔
788

112✔
789
// Stop signals all helper goroutines to execute a graceful shutdown. This
112✔
790
// method will block until all goroutines have exited.
112✔
791
func (f *Manager) Stop() error {
792
        f.stopped.Do(func() {
793
                log.Info("Funding manager shutting down...")
794
                defer log.Debug("Funding manager shutdown complete")
795

109✔
796
                close(f.quit)
217✔
797
                f.wg.Wait()
108✔
798
        })
108✔
799

108✔
800
        return nil
108✔
801
}
108✔
802

108✔
803
// rebroadcastFundingTx publishes the funding tx on startup for each
804
// unconfirmed channel.
109✔
805
func (f *Manager) rebroadcastFundingTx(c *channeldb.OpenChannel) {
806
        var fundingTxBuf bytes.Buffer
807
        err := c.FundingTxn.Serialize(&fundingTxBuf)
808
        if err != nil {
809
                log.Errorf("Unable to serialize funding transaction %v: %v",
6✔
810
                        c.FundingTxn.TxHash(), err)
6✔
811

6✔
812
                // Clear the buffer of any bytes that were written before the
6✔
813
                // serialization error to prevent logging an incomplete
×
814
                // transaction.
×
815
                fundingTxBuf.Reset()
×
UNCOV
816
        } else {
×
UNCOV
817
                log.Debugf("Rebroadcasting funding tx for ChannelPoint(%v): "+
×
UNCOV
818
                        "%x", c.FundingOutpoint, fundingTxBuf.Bytes())
×
UNCOV
819
        }
×
820

6✔
821
        // Set a nil short channel ID at this stage because we do not know it
6✔
822
        // until our funding tx confirms.
6✔
823
        label := labels.MakeLabel(labels.LabelTypeChannelOpen, nil)
6✔
824

825
        err = f.cfg.PublishTransaction(c.FundingTxn, label)
826
        if err != nil {
827
                log.Errorf("Unable to rebroadcast funding tx %x for "+
6✔
828
                        "ChannelPoint(%v): %v", fundingTxBuf.Bytes(),
6✔
829
                        c.FundingOutpoint, err)
6✔
830
        }
6✔
UNCOV
831
}
×
UNCOV
832

×
UNCOV
833
// PendingChanID is a type that represents a pending channel ID. This might be
×
UNCOV
834
// selected by the caller, but if not, will be automatically selected.
×
835
type PendingChanID = [32]byte
836

837
// nextPendingChanID returns the next free pending channel ID to be used to
838
// identify a particular future channel funding workflow.
839
func (f *Manager) nextPendingChanID() PendingChanID {
840
        // Obtain a fresh nonce. We do this by encoding the incremented nonce.
841
        nextNonce := f.chanIDNonce.Add(1)
842

843
        var nonceBytes [8]byte
60✔
844
        binary.LittleEndian.PutUint64(nonceBytes[:], nextNonce)
60✔
845

60✔
846
        // We'll generate the next pending channelID by "encrypting" 32-bytes
60✔
847
        // of zeroes which'll extract 32 random bytes from our stream cipher.
60✔
848
        var (
60✔
849
                nextChanID PendingChanID
60✔
850
                zeroes     [32]byte
60✔
851
        )
60✔
852
        salsa20.XORKeyStream(
60✔
853
                nextChanID[:], zeroes[:], nonceBytes[:], &f.chanIDKey,
60✔
854
        )
60✔
855

60✔
856
        return nextChanID
60✔
857
}
60✔
858

60✔
859
// CancelPeerReservations cancels all active reservations associated with the
60✔
860
// passed node. This will ensure any outputs which have been pre committed,
60✔
861
// (and thus locked from coin selection), are properly freed.
60✔
862
func (f *Manager) CancelPeerReservations(nodePub [33]byte) {
863
        log.Debugf("Cancelling all reservations for peer %x", nodePub[:])
864

865
        f.resMtx.Lock()
866
        defer f.resMtx.Unlock()
3✔
867

3✔
868
        // We'll attempt to look up this node in the set of active
3✔
869
        // reservations.  If they don't have any, then there's no further work
3✔
870
        // to be done.
3✔
871
        nodeReservations, ok := f.activeReservations[nodePub]
3✔
872
        if !ok {
3✔
873
                log.Debugf("No active reservations for node: %x", nodePub[:])
3✔
874
                return
3✔
875
        }
3✔
876

6✔
877
        // If they do have any active reservations, then we'll cancel all of
3✔
878
        // them (which releases any locked UTXO's), and also delete it from the
3✔
879
        // reservation map.
3✔
880
        for pendingID, resCtx := range nodeReservations {
881
                if err := resCtx.reservation.Cancel(); err != nil {
882
                        log.Errorf("unable to cancel reservation for "+
883
                                "node=%x: %v", nodePub[:], err)
884
                }
×
UNCOV
885

×
886
                resCtx.err <- fmt.Errorf("peer disconnected")
×
887
                delete(nodeReservations, pendingID)
×
UNCOV
888
        }
×
889

UNCOV
890
        // Finally, we'll delete the node itself from the set of reservations.
×
891
        delete(f.activeReservations, nodePub)
×
892
}
893

894
// chanIdentifier wraps pending channel ID and channel ID into one struct so
UNCOV
895
// it's easier to identify a specific channel.
×
896
//
897
// TODO(yy): move to a different package to hide the private fields so direct
898
// access is disabled.
899
type chanIdentifier struct {
900
        // tempChanID is the pending channel ID created by the funder when
901
        // initializing the funding flow. For fundee, it's received from the
902
        // `open_channel` message.
903
        tempChanID lnwire.ChannelID
904

905
        // chanID is the channel ID created by the funder once the
906
        // `accept_channel` message is received. For fundee, it's received from
907
        // the `funding_created` message.
908
        chanID lnwire.ChannelID
909

910
        // chanIDSet is a boolean indicates whether the active channel ID is
911
        // set for this identifier. For zero conf channels, the `chanID` can be
912
        // all-zero, which is the same as the empty value of `ChannelID`. To
913
        // avoid the confusion, we use this boolean to explicitly signal
914
        // whether the `chanID` is set or not.
915
        chanIDSet bool
916
}
917

918
// newChanIdentifier creates a new chanIdentifier.
919
func newChanIdentifier(tempChanID lnwire.ChannelID) *chanIdentifier {
920
        return &chanIdentifier{
921
                tempChanID: tempChanID,
922
        }
923
}
151✔
924

151✔
925
// setChanID updates the `chanIdentifier` with the active channel ID.
151✔
926
func (c *chanIdentifier) setChanID(chanID lnwire.ChannelID) {
151✔
927
        c.chanID = chanID
151✔
928
        c.chanIDSet = true
929
}
930

94✔
931
// hasChanID returns true if the active channel ID has been set.
94✔
932
func (c *chanIdentifier) hasChanID() bool {
94✔
933
        return c.chanIDSet
94✔
934
}
935

936
// failFundingFlow will fail the active funding flow with the target peer,
24✔
937
// identified by its unique temporary channel ID. This method will send an
24✔
938
// error to the remote peer, and also remove the reservation from our set of
24✔
939
// pending reservations.
940
//
941
// TODO(roasbeef): if peer disconnects, and haven't yet broadcast funding
942
// transaction, then all reservations should be cleared.
943
func (f *Manager) failFundingFlow(peer lnpeer.Peer, cid *chanIdentifier,
944
        fundingErr error) {
945

946
        log.Debugf("Failing funding flow for pending_id=%v: %v",
947
                cid.tempChanID, fundingErr)
948

24✔
949
        // First, notify Brontide to remove the pending channel.
24✔
950
        //
24✔
951
        // NOTE: depending on where we fail the flow, we may not have the
24✔
952
        // active channel ID yet.
24✔
953
        if cid.hasChanID() {
24✔
954
                err := peer.RemovePendingChannel(cid.chanID)
24✔
955
                if err != nil {
24✔
956
                        log.Errorf("Unable to remove channel %v with peer %x: "+
24✔
957
                                "%v", cid,
32✔
958
                                peer.IdentityKey().SerializeCompressed(), err)
8✔
959
                }
8✔
UNCOV
960
        }
×
UNCOV
961

×
UNCOV
962
        ctx, err := f.cancelReservationCtx(
×
UNCOV
963
                peer.IdentityKey(), cid.tempChanID, false,
×
964
        )
965
        if err != nil {
966
                log.Errorf("unable to cancel reservation: %v", err)
24✔
967
        }
24✔
968

24✔
969
        // In case the case where the reservation existed, send the funding
36✔
970
        // error on the error channel.
12✔
971
        if ctx != nil {
12✔
972
                ctx.err <- fundingErr
973
        }
974

975
        // We only send the exact error if it is part of out whitelisted set of
39✔
976
        // errors (lnwire.FundingError or lnwallet.ReservationError).
15✔
977
        var msg lnwire.ErrorData
15✔
978
        switch e := fundingErr.(type) {
979
        // Let the actual error message be sent to the remote for the
980
        // whitelisted types.
981
        case lnwallet.ReservationError:
24✔
982
                msg = lnwire.ErrorData(e.Error())
24✔
983
        case lnwire.FundingError:
984
                msg = lnwire.ErrorData(e.Error())
985
        case chanacceptor.ChanAcceptError:
8✔
986
                msg = lnwire.ErrorData(e.Error())
8✔
987

7✔
988
        // For all other error types we just send a generic error.
7✔
989
        default:
3✔
990
                msg = lnwire.ErrorData("funding failed due to internal error")
3✔
991
        }
992

993
        errMsg := &lnwire.Error{
15✔
994
                ChanID: cid.tempChanID,
15✔
995
                Data:   msg,
996
        }
997

24✔
998
        log.Debugf("Sending funding error to peer (%x): %v",
24✔
999
                peer.IdentityKey().SerializeCompressed(),
24✔
1000
                lnutils.SpewLogClosure(errMsg))
24✔
1001

24✔
1002
        if err := peer.SendMessage(false, errMsg); err != nil {
24✔
1003
                log.Errorf("unable to send error message to peer %v", err)
24✔
1004
        }
24✔
1005
}
24✔
1006

24✔
UNCOV
1007
// sendWarning sends a new warning message to the target peer, targeting the
×
UNCOV
1008
// specified cid with the passed funding error.
×
1009
func (f *Manager) sendWarning(peer lnpeer.Peer, cid *chanIdentifier,
1010
        fundingErr error) {
1011

1012
        msg := fundingErr.Error()
1013

1014
        errMsg := &lnwire.Warning{
×
1015
                ChanID: cid.tempChanID,
×
1016
                Data:   lnwire.WarningData(msg),
×
1017
        }
×
1018

×
1019
        log.Debugf("Sending funding warning to peer (%x): %v",
×
1020
                peer.IdentityKey().SerializeCompressed(),
×
1021
                lnutils.SpewLogClosure(errMsg),
×
1022
        )
×
1023

×
1024
        if err := peer.SendMessage(false, errMsg); err != nil {
×
1025
                log.Errorf("unable to send error message to peer %v", err)
×
1026
        }
×
UNCOV
1027
}
×
UNCOV
1028

×
UNCOV
1029
// reservationCoordinator is the primary goroutine tasked with progressing the
×
UNCOV
1030
// funding workflow between the wallet, and any outside peers or local callers.
×
1031
//
1032
// NOTE: This MUST be run as a goroutine.
1033
func (f *Manager) reservationCoordinator() {
1034
        defer f.wg.Done()
1035

1036
        zombieSweepTicker := time.NewTicker(f.cfg.ZombieSweeperInterval)
1037
        defer zombieSweepTicker.Stop()
112✔
1038

112✔
1039
        for {
112✔
1040
                select {
112✔
1041
                case fmsg := <-f.fundingMsgs:
112✔
1042
                        switch msg := fmsg.msg.(type) {
112✔
1043
                        case *lnwire.OpenChannel:
496✔
1044
                                f.fundeeProcessOpenChannel(fmsg.peer, msg)
384✔
1045

218✔
1046
                        case *lnwire.AcceptChannel:
218✔
1047
                                f.funderProcessAcceptChannel(fmsg.peer, msg)
57✔
1048

57✔
1049
                        case *lnwire.FundingCreated:
1050
                                f.fundeeProcessFundingCreated(fmsg.peer, msg)
36✔
1051

36✔
1052
                        case *lnwire.FundingSigned:
1053
                                f.funderProcessFundingSigned(fmsg.peer, msg)
31✔
1054

31✔
1055
                        case *lnwire.ChannelReady:
1056
                                f.wg.Add(1)
31✔
1057
                                go f.handleChannelReady(fmsg.peer, msg)
31✔
1058

1059
                        case *lnwire.Warning:
31✔
1060
                                f.handleWarningMsg(fmsg.peer, msg)
31✔
1061

31✔
1062
                        case *lnwire.Error:
1063
                                f.handleErrorMsg(fmsg.peer, msg)
44✔
1064
                        }
44✔
1065
                case req := <-f.fundingRequests:
1066
                        f.handleInitFundingMsg(req)
3✔
1067

3✔
1068
                case <-zombieSweepTicker.C:
1069
                        f.pruneZombieReservations()
60✔
1070

60✔
1071
                case <-f.quit:
1072
                        return
3✔
1073
                }
3✔
1074
        }
1075
}
108✔
1076

108✔
1077
// advanceFundingState will advance the channel through the steps after the
1078
// funding transaction is broadcasted, up until the point where the channel is
1079
// ready for operation. This includes waiting for the funding transaction to
1080
// confirm, sending channel_ready to the peer, adding the channel to the graph,
1081
// and announcing the channel. The updateChan can be set non-nil to get
1082
// OpenStatusUpdates.
1083
//
1084
// NOTE: This MUST be run as a goroutine.
1085
func (f *Manager) advanceFundingState(channel *channeldb.OpenChannel,
1086
        pendingChanID PendingChanID,
1087
        updateChan chan<- *lnrpc.OpenStatusUpdate) {
1088

1089
        defer f.wg.Done()
1090

1091
        // If the channel is still pending we must wait for the funding
68✔
1092
        // transaction to confirm.
68✔
1093
        if channel.IsPending {
68✔
1094
                err := f.advancePendingChannelState(channel, pendingChanID)
68✔
1095
                if err != nil {
68✔
1096
                        log.Errorf("Unable to advance pending state of "+
68✔
1097
                                "ChannelPoint(%v): %v",
128✔
1098
                                channel.FundingOutpoint, err)
60✔
1099
                        return
86✔
1100
                }
26✔
1101
        }
26✔
1102

26✔
1103
        var chanOpts []lnwallet.ChannelOpt
26✔
1104
        f.cfg.AuxLeafStore.WhenSome(func(s lnwallet.AuxLeafStore) {
26✔
1105
                chanOpts = append(chanOpts, lnwallet.WithLeafStore(s))
1106
        })
1107
        f.cfg.AuxSigner.WhenSome(func(s lnwallet.AuxSigner) {
45✔
1108
                chanOpts = append(chanOpts, lnwallet.WithAuxSigner(s))
87✔
1109
        })
42✔
1110
        f.cfg.AuxResolver.WhenSome(func(s lnwallet.AuxContractResolver) {
42✔
1111
                chanOpts = append(chanOpts, lnwallet.WithAuxResolver(s))
87✔
1112
        })
42✔
1113

42✔
1114
        // We create the state-machine object which wraps the database state.
45✔
UNCOV
1115
        lnChannel, err := lnwallet.NewLightningChannel(
×
UNCOV
1116
                nil, channel, nil, chanOpts...,
×
1117
        )
1118
        if err != nil {
1119
                log.Errorf("Unable to create LightningChannel(%v): %v",
45✔
1120
                        channel.FundingOutpoint, err)
45✔
1121
                return
45✔
1122
        }
45✔
UNCOV
1123

×
UNCOV
1124
        for {
×
UNCOV
1125
                channelState, shortChanID, err := f.getChannelOpeningState(
×
UNCOV
1126
                        &channel.FundingOutpoint,
×
1127
                )
1128
                if err == channeldb.ErrChannelNotFound {
196✔
1129
                        // Channel not in fundingManager's opening database,
151✔
1130
                        // meaning it was successfully announced to the
151✔
1131
                        // network.
151✔
1132
                        // TODO(halseth): could do graph consistency check
179✔
1133
                        // here, and re-add the edge if missing.
28✔
1134
                        log.Debugf("ChannelPoint(%v) with chan_id=%x not "+
28✔
1135
                                "found in opening database, assuming already "+
28✔
1136
                                "announced to the network",
28✔
1137
                                channel.FundingOutpoint, pendingChanID)
28✔
1138
                        return
28✔
1139
                } else if err != nil {
28✔
1140
                        log.Errorf("Unable to query database for "+
28✔
1141
                                "channel opening state(%v): %v",
28✔
1142
                                channel.FundingOutpoint, err)
28✔
1143
                        return
154✔
1144
                }
×
UNCOV
1145

×
UNCOV
1146
                // If we did find the channel in the opening state database, we
×
UNCOV
1147
                // have seen the funding transaction being confirmed, but there
×
UNCOV
1148
                // are still steps left of the setup procedure. We continue the
×
1149
                // procedure where we left off.
1150
                err = f.stateStep(
1151
                        channel, lnChannel, shortChanID, pendingChanID,
1152
                        channelState, updateChan,
1153
                )
1154
                if err != nil {
126✔
1155
                        log.Errorf("Unable to advance state(%v): %v",
126✔
1156
                                channel.FundingOutpoint, err)
126✔
1157
                        return
126✔
1158
                }
146✔
1159
        }
20✔
1160
}
20✔
1161

20✔
1162
// stateStep advances the confirmed channel one step in the funding state
20✔
1163
// machine. This method is synchronous and the new channel opening state will
1164
// have been written to the database when it successfully returns. The
1165
// updateChan can be set non-nil to get OpenStatusUpdates.
1166
func (f *Manager) stateStep(channel *channeldb.OpenChannel,
1167
        lnChannel *lnwallet.LightningChannel,
1168
        shortChanID *lnwire.ShortChannelID, pendingChanID PendingChanID,
1169
        channelState channelOpeningState,
1170
        updateChan chan<- *lnrpc.OpenStatusUpdate) error {
1171

1172
        chanID := lnwire.NewChanIDFromOutPoint(channel.FundingOutpoint)
1173
        log.Debugf("Channel(%v) with ShortChanID %v has opening state %v",
1174
                chanID, shortChanID, channelState)
126✔
1175

126✔
1176
        switch channelState {
126✔
1177
        // The funding transaction was confirmed, but we did not successfully
126✔
1178
        // send the channelReady message to the peer, so let's do that now.
126✔
1179
        case markedOpen:
126✔
1180
                err := f.sendChannelReady(channel, lnChannel)
126✔
1181
                if err != nil {
1182
                        return fmt.Errorf("failed sending channelReady: %w",
1183
                                err)
38✔
1184
                }
38✔
1185

39✔
1186
                // As the channelReady message is now sent to the peer, the
1✔
1187
                // channel is moved to the next state of the state machine. It
1✔
1188
                // will be moved to the last state (actually deleted from the
1✔
1189
                // database) after the channel is finally announced.
1190
                err = f.saveChannelOpeningState(
1191
                        &channel.FundingOutpoint, channelReadySent,
1192
                        shortChanID,
1193
                )
1194
                if err != nil {
37✔
1195
                        return fmt.Errorf("error setting channel state to"+
37✔
1196
                                " channelReadySent: %w", err)
37✔
1197
                }
37✔
1198

37✔
UNCOV
1199
                log.Debugf("Channel(%v) with ShortChanID %v: successfully "+
×
UNCOV
1200
                        "sent ChannelReady", chanID, shortChanID)
×
UNCOV
1201

×
1202
                return nil
1203

37✔
1204
        // channelReady was sent to peer, but the channel was not added to the
37✔
1205
        // graph and the channel announcement was not sent.
37✔
1206
        case channelReadySent:
37✔
1207
                // We must wait until we've received the peer's channel_ready
1208
                // before sending a channel_update according to BOLT#07.
1209
                received, err := f.receivedChannelReady(
1210
                        channel.IdentityPub, chanID,
63✔
1211
                )
63✔
1212
                if err != nil {
63✔
1213
                        return fmt.Errorf("failed to check if channel_ready "+
63✔
1214
                                "was received: %v", err)
63✔
1215
                }
63✔
1216

64✔
1217
                if !received {
1✔
1218
                        // We haven't received ChannelReady, so we'll continue
1✔
1219
                        // to the next iteration of the loop after sleeping for
1✔
1220
                        // checkPeerChannelReadyInterval.
1221
                        select {
100✔
1222
                        case <-time.After(checkPeerChannelReadyInterval):
38✔
1223
                        case <-f.quit:
38✔
1224
                                return ErrFundingManagerShuttingDown
38✔
1225
                        }
38✔
1226

27✔
1227
                        return nil
14✔
1228
                }
14✔
1229

1230
                return f.handleChannelReadyReceived(
1231
                        channel, shortChanID, pendingChanID, updateChan,
27✔
1232
                )
1233

1234
        // The channel was added to the Router's topology, but the channel
27✔
1235
        // announcement was not sent.
27✔
1236
        case addedToGraph:
27✔
1237
                if channel.IsZeroConf() {
1238
                        // If this is a zero-conf channel, then we will wait
1239
                        // for it to be confirmed before announcing it to the
1240
                        // greater network.
31✔
1241
                        err := f.waitForZeroConfChannel(channel)
40✔
1242
                        if err != nil {
9✔
1243
                                return fmt.Errorf("failed waiting for zero "+
9✔
1244
                                        "channel: %v", err)
9✔
1245
                        }
9✔
1246

14✔
1247
                        // Update the local shortChanID variable such that
5✔
1248
                        // annAfterSixConfs uses the confirmed SCID.
5✔
1249
                        confirmedScid := channel.ZeroConfRealScid()
5✔
1250
                        shortChanID = &confirmedScid
1251
                }
1252

1253
                err := f.annAfterSixConfs(channel, shortChanID)
7✔
1254
                if err != nil {
7✔
1255
                        return fmt.Errorf("error sending channel "+
1256
                                "announcement: %v", err)
1257
                }
29✔
1258

34✔
1259
                // We delete the channel opening state from our internal
5✔
1260
                // database as the opening process has succeeded. We can do
5✔
1261
                // this because we assume the AuthenticatedGossiper queues the
5✔
1262
                // announcement messages, and persists them in case of a daemon
1263
                // shutdown.
1264
                err = f.deleteChannelOpeningState(&channel.FundingOutpoint)
1265
                if err != nil {
1266
                        return fmt.Errorf("error deleting channel state: %w",
1267
                                err)
1268
                }
27✔
1269

27✔
UNCOV
1270
                // After the fee parameters have been stored in the
×
UNCOV
1271
                // announcement we can delete them from the database. For
×
UNCOV
1272
                // private channels we do not announce the channel policy to
×
1273
                // the network but still need to delete them from the database.
1274
                err = f.deleteInitialForwardingPolicy(chanID)
1275
                if err != nil {
1276
                        log.Infof("Could not delete initial policy for chanId "+
1277
                                "%x", chanID)
1278
                }
27✔
1279

27✔
UNCOV
1280
                log.Debugf("Channel(%v) with ShortChanID %v: successfully "+
×
UNCOV
1281
                        "announced", chanID, shortChanID)
×
UNCOV
1282

×
1283
                return nil
1284
        }
27✔
1285

27✔
1286
        return fmt.Errorf("undefined channelState: %v", channelState)
27✔
1287
}
27✔
1288

1289
// advancePendingChannelState waits for a pending channel's funding tx to
UNCOV
1290
// confirm, and marks it open in the database when that happens.
×
1291
func (f *Manager) advancePendingChannelState(channel *channeldb.OpenChannel,
1292
        pendingChanID PendingChanID) error {
1293

1294
        if channel.IsZeroConf() {
1295
                // Persist the alias to the alias database.
1296
                baseScid := channel.ShortChannelID
60✔
1297
                err := f.cfg.AliasManager.AddLocalAlias(
60✔
1298
                        baseScid, baseScid, true, false,
67✔
1299
                )
7✔
1300
                if err != nil {
7✔
1301
                        return fmt.Errorf("error adding local alias to "+
7✔
1302
                                "store: %v", err)
7✔
1303
                }
7✔
1304

7✔
UNCOV
1305
                // We don't wait for zero-conf channels to be confirmed and
×
UNCOV
1306
                // instead immediately proceed with the rest of the funding
×
UNCOV
1307
                // flow. The channel opening state is stored under the alias
×
1308
                // SCID.
1309
                err = f.saveChannelOpeningState(
1310
                        &channel.FundingOutpoint, markedOpen,
1311
                        &channel.ShortChannelID,
1312
                )
1313
                if err != nil {
7✔
1314
                        return fmt.Errorf("error setting zero-conf channel "+
7✔
1315
                                "state to markedOpen: %v", err)
7✔
1316
                }
7✔
1317

7✔
UNCOV
1318
                // The ShortChannelID is already set since it's an alias, but
×
UNCOV
1319
                // we still need to mark the channel as no longer pending.
×
UNCOV
1320
                err = channel.MarkAsOpen(channel.ShortChannelID)
×
1321
                if err != nil {
1322
                        return fmt.Errorf("error setting zero-conf channel's "+
1323
                                "pending flag to false: %v", err)
1324
                }
7✔
1325

7✔
UNCOV
1326
                // Inform the ChannelNotifier that the channel has transitioned
×
UNCOV
1327
                // from pending open to open.
×
UNCOV
1328
                f.cfg.NotifyOpenChannelEvent(
×
1329
                        channel.FundingOutpoint, channel.IdentityPub,
1330
                )
1331

1332
                // Find and close the discoverySignal for this channel such
7✔
1333
                // that ChannelReady messages will be processed.
7✔
1334
                chanID := lnwire.NewChanIDFromOutPoint(channel.FundingOutpoint)
7✔
1335
                discoverySignal, ok := f.localDiscoverySignals.Load(chanID)
7✔
1336
                if ok {
7✔
1337
                        close(discoverySignal)
7✔
1338
                }
7✔
1339

7✔
1340
                return nil
14✔
1341
        }
7✔
1342

7✔
1343
        confChannel, err := f.waitForFundingWithTimeout(channel)
1344
        if err == ErrConfirmationTimeout {
7✔
1345
                return f.fundingTimeout(channel, pendingChanID)
1346
        } else if err != nil {
1347
                return fmt.Errorf("error waiting for funding "+
56✔
1348
                        "confirmation for ChannelPoint(%v): %v",
61✔
1349
                        channel.FundingOutpoint, err)
5✔
1350
        }
83✔
1351

24✔
1352
        if blockchain.IsCoinBaseTx(confChannel.fundingTx) {
24✔
1353
                // If it's a coinbase transaction, we need to wait for it to
24✔
1354
                // mature. We wait out an additional MinAcceptDepth on top of
24✔
1355
                // the coinbase maturity as an extra margin of safety.
1356
                maturity := f.cfg.Wallet.Cfg.NetParams.CoinbaseMaturity
35✔
1357
                numCoinbaseConfs := uint32(maturity)
2✔
1358

2✔
1359
                if channel.NumConfsRequired > maturity {
2✔
1360
                        numCoinbaseConfs = uint32(channel.NumConfsRequired)
2✔
1361
                }
2✔
1362

2✔
1363
                txid := &channel.FundingOutpoint.Hash
2✔
UNCOV
1364
                fundingScript, err := makeFundingScript(channel)
×
UNCOV
1365
                if err != nil {
×
1366
                        log.Errorf("unable to create funding script for "+
1367
                                "ChannelPoint(%v): %v",
2✔
1368
                                channel.FundingOutpoint, err)
2✔
1369

2✔
1370
                        return err
×
1371
                }
×
UNCOV
1372

×
UNCOV
1373
                confNtfn, err := f.cfg.Notifier.RegisterConfirmationsNtfn(
×
UNCOV
1374
                        txid, fundingScript, numCoinbaseConfs,
×
UNCOV
1375
                        channel.BroadcastHeight(),
×
1376
                )
1377
                if err != nil {
2✔
1378
                        log.Errorf("Unable to register for confirmation of "+
2✔
1379
                                "ChannelPoint(%v): %v",
2✔
1380
                                channel.FundingOutpoint, err)
2✔
1381

2✔
1382
                        return err
×
1383
                }
×
UNCOV
1384

×
UNCOV
1385
                select {
×
UNCOV
1386
                case _, ok := <-confNtfn.Confirmed:
×
UNCOV
1387
                        if !ok {
×
1388
                                return fmt.Errorf("ChainNotifier shutting "+
1389
                                        "down, can't complete funding flow "+
2✔
1390
                                        "for ChannelPoint(%v)",
2✔
1391
                                        channel.FundingOutpoint)
2✔
1392
                        }
×
UNCOV
1393

×
1394
                case <-f.quit:
×
1395
                        return ErrFundingManagerShuttingDown
×
UNCOV
1396
                }
×
1397
        }
UNCOV
1398

×
UNCOV
1399
        // Success, funding transaction was confirmed.
×
1400
        chanID := lnwire.NewChanIDFromOutPoint(channel.FundingOutpoint)
1401
        log.Debugf("ChannelID(%v) is now fully confirmed! "+
1402
                "(shortChanID=%v)", chanID, confChannel.shortChanID)
1403

1404
        err = f.handleFundingConfirmation(channel, confChannel)
33✔
1405
        if err != nil {
33✔
1406
                return fmt.Errorf("unable to handle funding "+
33✔
1407
                        "confirmation for ChannelPoint(%v): %v",
33✔
1408
                        channel.FundingOutpoint, err)
33✔
1409
        }
33✔
UNCOV
1410

×
UNCOV
1411
        return nil
×
UNCOV
1412
}
×
UNCOV
1413

×
1414
// ProcessFundingMsg sends a message to the internal fundingManager goroutine,
1415
// allowing it to handle the lnwire.Message.
33✔
1416
func (f *Manager) ProcessFundingMsg(msg lnwire.Message, peer lnpeer.Peer) {
1417
        select {
1418
        case f.fundingMsgs <- &fundingMsg{msg, peer}:
1419
        case <-f.quit:
1420
                return
219✔
1421
        }
219✔
1422
}
219✔
UNCOV
1423

×
UNCOV
1424
// fundeeProcessOpenChannel creates an initial 'ChannelReservation' within the
×
1425
// wallet, then responds to the source peer with an accept channel message
1426
// progressing the funding workflow.
1427
//
1428
// TODO(roasbeef): add error chan to all, let channelManager handle
1429
// error+propagate.
1430
//
1431
//nolint:funlen
1432
func (f *Manager) fundeeProcessOpenChannel(peer lnpeer.Peer,
1433
        msg *lnwire.OpenChannel) {
1434

1435
        // Check number of pending channels to be smaller than maximum allowed
1436
        // number and send ErrorGeneric to remote peer if condition is
1437
        // violated.
57✔
1438
        peerPubKey := peer.IdentityKey()
57✔
1439
        peerIDKey := newSerializedKey(peerPubKey)
57✔
1440

57✔
1441
        amt := msg.FundingAmount
57✔
1442

57✔
1443
        // We get all pending channels for this peer. This is the list of the
57✔
1444
        // active reservations and the channels pending open in the database.
57✔
1445
        f.resMtx.RLock()
57✔
1446
        reservations := f.activeReservations[peerIDKey]
57✔
1447

57✔
1448
        // We don't count reservations that were created from a canned funding
57✔
1449
        // shim. The user has registered the shim and therefore expects this
57✔
1450
        // channel to arrive.
57✔
1451
        numPending := 0
57✔
1452
        for _, res := range reservations {
57✔
1453
                if !res.reservation.IsCannedShim() {
57✔
1454
                        numPending++
57✔
1455
                }
57✔
1456
        }
69✔
1457
        f.resMtx.RUnlock()
24✔
1458

12✔
1459
        // Create the channel identifier.
12✔
1460
        cid := newChanIdentifier(msg.PendingChannelID)
1461

57✔
1462
        // Also count the channels that are already pending. There we don't know
57✔
1463
        // the underlying intent anymore, unfortunately.
57✔
1464
        channels, err := f.cfg.ChannelDB.FetchOpenChannels(peerPubKey)
57✔
1465
        if err != nil {
57✔
1466
                f.failFundingFlow(peer, cid, err)
57✔
1467
                return
57✔
1468
        }
57✔
1469

57✔
UNCOV
1470
        for _, c := range channels {
×
UNCOV
1471
                // Pending channels that have a non-zero thaw height were also
×
UNCOV
1472
                // created through a canned funding shim. Those also don't
×
1473
                // count towards the DoS protection limit.
1474
                //
72✔
1475
                // TODO(guggero): Properly store the funding type (wallet, shim,
15✔
1476
                // PSBT) on the channel so we don't need to use the thaw height.
15✔
1477
                if c.IsPending && c.ThawHeight == 0 {
15✔
1478
                        numPending++
15✔
1479
                }
15✔
1480
        }
15✔
1481

26✔
1482
        // TODO(roasbeef): modify to only accept a _single_ pending channel per
11✔
1483
        // block unless white listed
11✔
1484
        if numPending >= f.cfg.MaxPendingChannels {
1485
                f.failFundingFlow(peer, cid, lnwire.ErrMaxPendingChannels)
1486

1487
                return
1488
        }
64✔
1489

7✔
1490
        // Ensure that the pendingChansLimit is respected.
7✔
1491
        pendingChans, err := f.cfg.ChannelDB.FetchPendingChannels()
7✔
1492
        if err != nil {
7✔
1493
                f.failFundingFlow(peer, cid, err)
1494
                return
1495
        }
53✔
1496

53✔
UNCOV
1497
        if len(pendingChans) > pendingChansLimit {
×
1498
                f.failFundingFlow(peer, cid, lnwire.ErrMaxPendingChannels)
×
1499
                return
×
1500
        }
1501

53✔
UNCOV
1502
        // We'll also reject any requests to create channels until we're fully
×
UNCOV
1503
        // synced to the network as we won't be able to properly validate the
×
UNCOV
1504
        // confirmation of the funding transaction.
×
1505
        isSynced, _, err := f.cfg.Wallet.IsSynced()
1506
        if err != nil || !isSynced {
1507
                if err != nil {
1508
                        log.Errorf("unable to query wallet: %v", err)
1509
                }
53✔
1510
                err := errors.New("Synchronizing blockchain")
53✔
1511
                f.failFundingFlow(peer, cid, err)
×
1512
                return
×
UNCOV
1513
        }
×
UNCOV
1514

×
UNCOV
1515
        // Ensure that the remote party respects our maximum channel size.
×
UNCOV
1516
        if amt > f.cfg.MaxChanSize {
×
1517
                f.failFundingFlow(
1518
                        peer, cid,
1519
                        lnwallet.ErrChanTooLarge(amt, f.cfg.MaxChanSize),
1520
                )
58✔
1521
                return
5✔
1522
        }
5✔
1523

5✔
1524
        // We'll, also ensure that the remote party isn't attempting to propose
5✔
1525
        // a channel that's below our current min channel size.
5✔
1526
        if amt < f.cfg.MinChanSize {
5✔
1527
                f.failFundingFlow(
1528
                        peer, cid,
1529
                        lnwallet.ErrChanTooSmall(amt, f.cfg.MinChanSize),
1530
                )
54✔
1531
                return
3✔
1532
        }
3✔
1533

3✔
1534
        // If request specifies non-zero push amount and 'rejectpush' is set,
3✔
1535
        // signal an error.
3✔
1536
        if f.cfg.RejectPush && msg.PushAmount > 0 {
3✔
1537
                f.failFundingFlow(peer, cid, lnwallet.ErrNonZeroPushAmount())
1538
                return
1539
        }
1540

52✔
1541
        // Send the OpenChannel request to the ChannelAcceptor to determine
1✔
1542
        // whether this node will accept the channel.
1✔
1543
        chanReq := &chanacceptor.ChannelAcceptRequest{
1✔
1544
                Node:        peer.IdentityKey(),
1545
                OpenChanMsg: msg,
1546
        }
1547

50✔
1548
        // Query our channel acceptor to determine whether we should reject
50✔
1549
        // the channel.
50✔
1550
        acceptorResp := f.cfg.OpenChannelPredicate.Accept(chanReq)
50✔
1551
        if acceptorResp.RejectChannel() {
50✔
1552
                f.failFundingFlow(peer, cid, acceptorResp.ChanAcceptError)
50✔
1553
                return
50✔
1554
        }
50✔
1555

53✔
1556
        log.Infof("Recv'd fundingRequest(amt=%v, push=%v, delay=%v, "+
3✔
1557
                "pendingId=%x) from peer(%x)", amt, msg.PushAmount,
3✔
1558
                msg.CsvDelay, msg.PendingChannelID,
3✔
1559
                peer.IdentityKey().SerializeCompressed())
1560

50✔
1561
        // Attempt to initialize a reservation within the wallet. If the wallet
50✔
1562
        // has insufficient resources to create the channel, then the
50✔
1563
        // reservation attempt may be rejected. Note that since we're on the
50✔
1564
        // responding side of a single funder workflow, we don't commit any
50✔
1565
        // funds to the channel ourselves.
50✔
1566
        //
50✔
1567
        // Before we init the channel, we'll also check to see what commitment
50✔
1568
        // format we can use with this peer. This is dependent on *both* us and
50✔
1569
        // the remote peer are signaling the proper feature bit if we're using
50✔
1570
        // implicit negotiation, and simply the channel type sent over if we're
50✔
1571
        // using explicit negotiation.
50✔
1572
        chanType, commitType, err := negotiateCommitmentType(
50✔
1573
                msg.ChannelType, peer.LocalFeatures(), peer.RemoteFeatures(),
50✔
1574
        )
50✔
1575
        if err != nil {
50✔
1576
                // TODO(roasbeef): should be using soft errors
50✔
1577
                log.Errorf("channel type negotiation failed: %v", err)
50✔
1578
                f.failFundingFlow(peer, cid, err)
50✔
1579
                return
50✔
1580
        }
×
UNCOV
1581

×
UNCOV
1582
        var scidFeatureVal bool
×
UNCOV
1583
        if hasFeatures(
×
UNCOV
1584
                peer.LocalFeatures(), peer.RemoteFeatures(),
×
1585
                lnwire.ScidAliasOptional,
1586
        ) {
50✔
1587

50✔
1588
                scidFeatureVal = true
50✔
1589
        }
50✔
1590

56✔
1591
        var (
6✔
1592
                zeroConf bool
6✔
1593
                scid     bool
6✔
1594
        )
1595

50✔
1596
        // Only echo back a channel type in AcceptChannel if we actually used
50✔
1597
        // explicit negotiation above.
50✔
1598
        if chanType != nil {
50✔
1599
                // Check if the channel type includes the zero-conf or
50✔
1600
                // scid-alias bits.
50✔
1601
                featureVec := lnwire.RawFeatureVector(*chanType)
50✔
1602
                zeroConf = featureVec.IsSet(lnwire.ZeroConfRequired)
57✔
1603
                scid = featureVec.IsSet(lnwire.ScidAliasRequired)
7✔
1604

7✔
1605
                // If the zero-conf channel type was negotiated, ensure that
7✔
1606
                // the acceptor allows it.
7✔
1607
                if zeroConf && !acceptorResp.ZeroConf {
7✔
1608
                        // Fail the funding flow.
7✔
1609
                        flowErr := fmt.Errorf("channel acceptor blocked " +
7✔
1610
                                "zero-conf channel negotiation")
7✔
1611
                        log.Errorf("Cancelling funding flow for %v based on "+
7✔
1612
                                "channel acceptor response: %v", cid, flowErr)
×
1613
                        f.failFundingFlow(peer, cid, flowErr)
×
1614
                        return
×
1615
                }
×
UNCOV
1616

×
UNCOV
1617
                // If the zero-conf channel type wasn't negotiated and the
×
UNCOV
1618
                // fundee still wants a zero-conf channel, perform more checks.
×
UNCOV
1619
                // Require that both sides have the scid-alias feature bit set.
×
1620
                // We don't require anchors here - this is for compatibility
1621
                // with LDK.
1622
                if !zeroConf && acceptorResp.ZeroConf {
1623
                        if !scidFeatureVal {
1624
                                // Fail the funding flow.
1625
                                flowErr := fmt.Errorf("scid-alias feature " +
1626
                                        "must be negotiated for zero-conf")
7✔
1627
                                log.Errorf("Cancelling funding flow for "+
×
1628
                                        "zero-conf channel %v: %v", cid,
×
1629
                                        flowErr)
×
1630
                                f.failFundingFlow(peer, cid, flowErr)
×
1631
                                return
×
1632
                        }
×
UNCOV
1633

×
UNCOV
1634
                        // Set zeroConf to true to enable the zero-conf flow.
×
1635
                        zeroConf = true
×
UNCOV
1636
                }
×
1637
        }
1638

UNCOV
1639
        public := msg.ChannelFlags&lnwire.FFAnnounceChannel != 0
×
1640
        switch {
1641
        // Sending the option-scid-alias channel type for a public channel is
1642
        // disallowed.
1643
        case public && scid:
50✔
1644
                err = fmt.Errorf("option-scid-alias chantype for public " +
50✔
1645
                        "channel")
1646
                log.Errorf("Cancelling funding flow for public channel %v "+
1647
                        "with scid-alias: %v", cid, err)
×
1648
                f.failFundingFlow(peer, cid, err)
×
1649

×
1650
                return
×
UNCOV
1651

×
UNCOV
1652
        // The current variant of taproot channels can only be used with
×
UNCOV
1653
        // unadvertised channels for now.
×
1654
        case commitType.IsTaproot() && public:
×
1655
                err = fmt.Errorf("taproot channel type for public channel")
1656
                log.Errorf("Cancelling funding flow for public taproot "+
1657
                        "channel %v: %v", cid, err)
1658
                f.failFundingFlow(peer, cid, err)
×
1659

×
1660
                return
×
UNCOV
1661
        }
×
UNCOV
1662

×
UNCOV
1663
        // At this point, if we have an AuxFundingController active, we'll
×
UNCOV
1664
        // check to see if we have a special tapscript root to use in our
×
1665
        // MuSig funding output.
1666
        tapscriptRoot, err := fn.MapOptionZ(
1667
                f.cfg.AuxFundingController,
1668
                func(c AuxFundingController) AuxTapscriptResult {
1669
                        return c.DeriveTapscriptRoot(msg.PendingChannelID)
1670
                },
50✔
1671
        ).Unpack()
50✔
1672
        if err != nil {
50✔
1673
                err = fmt.Errorf("error deriving tapscript root: %w", err)
×
1674
                log.Error(err)
×
1675
                f.failFundingFlow(peer, cid, err)
1676

50✔
1677
                return
×
1678
        }
×
UNCOV
1679

×
UNCOV
1680
        req := &lnwallet.InitFundingReserveMsg{
×
UNCOV
1681
                ChainHash:        &msg.ChainHash,
×
UNCOV
1682
                PendingChanID:    msg.PendingChannelID,
×
1683
                NodeID:           peer.IdentityKey(),
1684
                NodeAddr:         peer.Address(),
50✔
1685
                LocalFundingAmt:  0,
50✔
1686
                RemoteFundingAmt: amt,
50✔
1687
                CommitFeePerKw:   chainfee.SatPerKWeight(msg.FeePerKiloWeight),
50✔
1688
                FundingFeePerKw:  0,
50✔
1689
                PushMSat:         msg.PushAmount,
50✔
1690
                Flags:            msg.ChannelFlags,
50✔
1691
                MinConfs:         1,
50✔
1692
                CommitType:       commitType,
50✔
1693
                ZeroConf:         zeroConf,
50✔
1694
                OptionScidAlias:  scid,
50✔
1695
                ScidAliasFeature: scidFeatureVal,
50✔
1696
                TapscriptRoot:    tapscriptRoot,
50✔
1697
        }
50✔
1698

50✔
1699
        reservation, err := f.cfg.Wallet.InitChannelReservation(req)
50✔
1700
        if err != nil {
50✔
1701
                log.Errorf("Unable to initialize reservation: %v", err)
50✔
1702
                f.failFundingFlow(peer, cid, err)
50✔
1703
                return
50✔
1704
        }
50✔
UNCOV
1705

×
UNCOV
1706
        log.Debugf("Initialized channel reservation: zeroConf=%v, psbt=%v, "+
×
UNCOV
1707
                "cannedShim=%v", reservation.IsZeroConf(),
×
UNCOV
1708
                reservation.IsPsbt(), reservation.IsCannedShim())
×
1709

1710
        if zeroConf {
50✔
1711
                // Store an alias for zero-conf channels. Other option-scid
50✔
1712
                // channels will do this at a later point.
50✔
1713
                aliasScid, err := f.cfg.AliasManager.RequestAlias()
50✔
1714
                if err != nil {
55✔
1715
                        log.Errorf("Unable to request alias: %v", err)
5✔
1716
                        f.failFundingFlow(peer, cid, err)
5✔
1717
                        return
5✔
1718
                }
5✔
UNCOV
1719

×
UNCOV
1720
                reservation.AddAlias(aliasScid)
×
UNCOV
1721
        }
×
UNCOV
1722

×
1723
        // As we're the responder, we get to specify the number of confirmations
1724
        // that we require before both of us consider the channel open. We'll
5✔
1725
        // use our mapping to derive the proper number of confirmations based on
1726
        // the amount of the channel, and also if any funds are being pushed to
1727
        // us. If a depth value was set by our channel acceptor, we will use
1728
        // that value instead.
1729
        numConfsReq := f.cfg.NumRequiredConfs(msg.FundingAmount, msg.PushAmount)
1730
        if acceptorResp.MinAcceptDepth != 0 {
1731
                numConfsReq = acceptorResp.MinAcceptDepth
1732
        }
1733

50✔
1734
        // We'll ignore the min_depth calculated above if this is a zero-conf
50✔
UNCOV
1735
        // channel.
×
UNCOV
1736
        if zeroConf {
×
1737
                numConfsReq = 0
1738
        }
1739

1740
        reservation.SetNumConfsRequired(numConfsReq)
55✔
1741

5✔
1742
        // We'll also validate and apply all the constraints the initiating
5✔
1743
        // party is attempting to dictate for our commitment transaction.
1744
        stateBounds := &channeldb.ChannelStateBounds{
50✔
1745
                ChanReserve:      msg.ChannelReserve,
50✔
1746
                MaxPendingAmount: msg.MaxValueInFlight,
50✔
1747
                MinHTLC:          msg.HtlcMinimum,
50✔
1748
                MaxAcceptedHtlcs: msg.MaxAcceptedHTLCs,
50✔
1749
        }
50✔
1750
        commitParams := &channeldb.CommitmentParams{
50✔
1751
                DustLimit: msg.DustLimit,
50✔
1752
                CsvDelay:  msg.CsvDelay,
50✔
1753
        }
50✔
1754
        err = reservation.CommitConstraints(
50✔
1755
                stateBounds, commitParams, f.cfg.MaxLocalCSVDelay, true,
50✔
1756
        )
50✔
1757
        if err != nil {
50✔
1758
                log.Errorf("Unacceptable channel constraints: %v", err)
50✔
1759
                f.failFundingFlow(peer, cid, err)
50✔
1760
                return
50✔
1761
        }
50✔
UNCOV
1762

×
UNCOV
1763
        // Check whether the peer supports upfront shutdown, and get a new
×
UNCOV
1764
        // wallet address if our node is configured to set shutdown addresses by
×
UNCOV
1765
        // default. We use the upfront shutdown script provided by our channel
×
1766
        // acceptor (if any) in lieu of user input.
1767
        shutdown, err := getUpfrontShutdownScript(
1768
                f.cfg.EnableUpfrontShutdown, peer, acceptorResp.UpfrontShutdown,
1769
                f.selectShutdownScript,
1770
        )
50✔
1771
        if err != nil {
100✔
1772
                f.failFundingFlow(
50✔
1773
                        peer, cid,
53✔
1774
                        fmt.Errorf("getUpfrontShutdownScript error: %w", err),
3✔
1775
                )
3✔
1776
                return
1777
        }
1778
        reservation.SetOurUpfrontShutdown(shutdown)
1779

1780
        // If a script enforced channel lease is being proposed, we'll need to
1781
        // validate its custom TLV records.
1782
        if commitType == lnwallet.CommitmentTypeScriptEnforcedLease {
1783
                if msg.LeaseExpiry == nil {
50✔
1784
                        err := errors.New("missing lease expiry")
50✔
1785
                        f.failFundingFlow(peer, cid, err)
50✔
1786
                        return
50✔
1787
                }
50✔
UNCOV
1788

×
UNCOV
1789
                // If we had a shim registered for this channel prior to
×
UNCOV
1790
                // receiving its corresponding OpenChannel message, then we'll
×
UNCOV
1791
                // validate the proposed LeaseExpiry against what was registered
×
UNCOV
1792
                // in our shim.
×
UNCOV
1793
                if reservation.LeaseExpiry() != 0 {
×
1794
                        if uint32(*msg.LeaseExpiry) !=
50✔
1795
                                reservation.LeaseExpiry() {
50✔
1796

50✔
1797
                                err := errors.New("lease expiry mismatch")
50✔
1798
                                f.failFundingFlow(peer, cid, err)
53✔
1799
                                return
3✔
1800
                        }
×
UNCOV
1801
                }
×
UNCOV
1802
        }
×
UNCOV
1803

×
1804
        log.Infof("Requiring %v confirmations for pendingChan(%x): "+
1805
                "amt=%v, push_amt=%v, committype=%v, upfrontShutdown=%x",
1806
                numConfsReq, msg.PendingChannelID, amt, msg.PushAmount,
1807
                commitType, msg.UpfrontShutdownScript)
1808

1809
        // Generate our required constraints for the remote party, using the
6✔
1810
        // values provided by the channel acceptor if they are non-zero.
3✔
1811
        remoteCsvDelay := f.cfg.RequiredRemoteDelay(amt)
3✔
UNCOV
1812
        if acceptorResp.CSVDelay != 0 {
×
1813
                remoteCsvDelay = acceptorResp.CSVDelay
×
1814
        }
×
UNCOV
1815

×
UNCOV
1816
        // If our default dust limit was above their ChannelReserve, we change
×
1817
        // it to the ChannelReserve. We must make sure the ChannelReserve we
1818
        // send in the AcceptChannel message is above both dust limits.
1819
        // Therefore, take the maximum of msg.DustLimit and our dust limit.
1820
        //
50✔
1821
        // NOTE: Even with this bounding, the ChannelAcceptor may return an
50✔
1822
        // BOLT#02-invalid ChannelReserve.
50✔
1823
        maxDustLimit := reservation.OurContribution().DustLimit
50✔
1824
        if msg.DustLimit > maxDustLimit {
50✔
1825
                maxDustLimit = msg.DustLimit
50✔
1826
        }
50✔
1827

50✔
1828
        chanReserve := f.cfg.RequiredRemoteChanReserve(amt, maxDustLimit)
50✔
UNCOV
1829
        if acceptorResp.Reserve != 0 {
×
1830
                chanReserve = acceptorResp.Reserve
×
1831
        }
1832

1833
        remoteMaxValue := f.cfg.RequiredRemoteMaxValue(amt)
1834
        if acceptorResp.InFlightTotal != 0 {
1835
                remoteMaxValue = acceptorResp.InFlightTotal
1836
        }
1837

1838
        maxHtlcs := f.cfg.RequiredRemoteMaxHTLCs(amt)
1839
        if acceptorResp.HtlcLimit != 0 {
50✔
1840
                maxHtlcs = acceptorResp.HtlcLimit
50✔
1841
        }
×
UNCOV
1842

×
1843
        // Default to our default minimum hltc value, replacing it with the
1844
        // channel acceptor's value if it is set.
50✔
1845
        minHtlc := f.cfg.DefaultMinHtlcIn
50✔
UNCOV
1846
        if acceptorResp.MinHtlcIn != 0 {
×
1847
                minHtlc = acceptorResp.MinHtlcIn
×
1848
        }
1849

50✔
1850
        // If we are handling a FundingOpen request then we need to specify the
50✔
UNCOV
1851
        // default channel fees since they are not provided by the responder
×
UNCOV
1852
        // interactively.
×
1853
        ourContribution := reservation.OurContribution()
1854
        forwardingPolicy := f.defaultForwardingPolicy(
50✔
1855
                ourContribution.ChannelStateBounds,
50✔
UNCOV
1856
        )
×
UNCOV
1857

×
1858
        // Once the reservation has been created successfully, we add it to
1859
        // this peer's map of pending reservations to track this particular
1860
        // reservation until either abort or completion.
1861
        f.resMtx.Lock()
50✔
1862
        if _, ok := f.activeReservations[peerIDKey]; !ok {
50✔
UNCOV
1863
                f.activeReservations[peerIDKey] = make(pendingChannels)
×
UNCOV
1864
        }
×
1865
        resCtx := &reservationWithCtx{
1866
                reservation:       reservation,
1867
                chanAmt:           amt,
1868
                forwardingPolicy:  *forwardingPolicy,
1869
                remoteCsvDelay:    remoteCsvDelay,
50✔
1870
                remoteMinHtlc:     minHtlc,
50✔
1871
                remoteMaxValue:    remoteMaxValue,
50✔
1872
                remoteMaxHtlcs:    maxHtlcs,
50✔
1873
                remoteChanReserve: chanReserve,
50✔
1874
                maxLocalCsv:       f.cfg.MaxLocalCSVDelay,
50✔
1875
                channelType:       chanType,
50✔
1876
                err:               make(chan error, 1),
50✔
1877
                peer:              peer,
50✔
1878
        }
96✔
1879
        f.activeReservations[peerIDKey][msg.PendingChannelID] = resCtx
46✔
1880
        f.resMtx.Unlock()
46✔
1881

50✔
1882
        // Update the timestamp once the fundingOpenMsg has been handled.
50✔
1883
        defer resCtx.updateTimestamp()
50✔
1884

50✔
1885
        cfg := channeldb.ChannelConfig{
50✔
1886
                ChannelStateBounds: channeldb.ChannelStateBounds{
50✔
1887
                        MaxPendingAmount: remoteMaxValue,
50✔
1888
                        ChanReserve:      chanReserve,
50✔
1889
                        MinHTLC:          minHtlc,
50✔
1890
                        MaxAcceptedHtlcs: maxHtlcs,
50✔
1891
                },
50✔
1892
                CommitmentParams: channeldb.CommitmentParams{
50✔
1893
                        DustLimit: msg.DustLimit,
50✔
1894
                        CsvDelay:  remoteCsvDelay,
50✔
1895
                },
50✔
1896
                MultiSigKey: keychain.KeyDescriptor{
50✔
1897
                        PubKey: copyPubKey(msg.FundingKey),
50✔
1898
                },
50✔
1899
                RevocationBasePoint: keychain.KeyDescriptor{
50✔
1900
                        PubKey: copyPubKey(msg.RevocationPoint),
50✔
1901
                },
50✔
1902
                PaymentBasePoint: keychain.KeyDescriptor{
50✔
1903
                        PubKey: copyPubKey(msg.PaymentPoint),
50✔
1904
                },
50✔
1905
                DelayBasePoint: keychain.KeyDescriptor{
50✔
1906
                        PubKey: copyPubKey(msg.DelayedPaymentPoint),
50✔
1907
                },
50✔
1908
                HtlcBasePoint: keychain.KeyDescriptor{
50✔
1909
                        PubKey: copyPubKey(msg.HtlcPoint),
50✔
1910
                },
50✔
1911
        }
50✔
1912

50✔
1913
        // With our parameters set, we'll now process their contribution so we
50✔
1914
        // can move the funding workflow ahead.
50✔
1915
        remoteContribution := &lnwallet.ChannelContribution{
50✔
1916
                FundingAmount:        amt,
50✔
1917
                FirstCommitmentPoint: msg.FirstCommitmentPoint,
50✔
1918
                ChannelConfig:        &cfg,
50✔
1919
                UpfrontShutdown:      msg.UpfrontShutdownScript,
50✔
1920
        }
50✔
1921

50✔
1922
        if resCtx.reservation.IsTaproot() {
50✔
1923
                localNonce, err := msg.LocalNonce.UnwrapOrErrV(errNoLocalNonce)
50✔
1924
                if err != nil {
50✔
1925
                        log.Error(errNoLocalNonce)
50✔
1926

50✔
1927
                        f.failFundingFlow(resCtx.peer, cid, errNoLocalNonce)
50✔
1928

50✔
1929
                        return
50✔
1930
                }
50✔
1931

50✔
1932
                remoteContribution.LocalNonce = &musig2.Nonces{
50✔
1933
                        PubNonce: localNonce,
50✔
1934
                }
50✔
1935
        }
50✔
1936

50✔
1937
        err = reservation.ProcessSingleContribution(remoteContribution)
50✔
1938
        if err != nil {
55✔
1939
                log.Errorf("unable to add contribution reservation: %v", err)
5✔
1940
                f.failFundingFlow(peer, cid, err)
5✔
UNCOV
1941
                return
×
UNCOV
1942
        }
×
UNCOV
1943

×
UNCOV
1944
        log.Infof("Sending fundingResp for pending_id(%x)",
×
UNCOV
1945
                msg.PendingChannelID)
×
UNCOV
1946
        bounds := remoteContribution.ChannelConfig.ChannelStateBounds
×
1947
        log.Debugf("Remote party accepted channel state space bounds: %v",
1948
                lnutils.SpewLogClosure(bounds))
5✔
1949
        params := remoteContribution.ChannelConfig.CommitmentParams
5✔
1950
        log.Debugf("Remote party accepted commitment rendering params: %v",
5✔
1951
                lnutils.SpewLogClosure(params))
1952

1953
        reservation.SetState(lnwallet.SentAcceptChannel)
50✔
1954

56✔
1955
        // With the initiator's contribution recorded, respond with our
6✔
1956
        // contribution in the next message of the workflow.
6✔
1957
        fundingAccept := lnwire.AcceptChannel{
6✔
1958
                PendingChannelID:      msg.PendingChannelID,
6✔
1959
                DustLimit:             ourContribution.DustLimit,
1960
                MaxValueInFlight:      remoteMaxValue,
44✔
1961
                ChannelReserve:        chanReserve,
44✔
1962
                MinAcceptDepth:        uint32(numConfsReq),
44✔
1963
                HtlcMinimum:           minHtlc,
44✔
1964
                CsvDelay:              remoteCsvDelay,
44✔
1965
                MaxAcceptedHTLCs:      maxHtlcs,
44✔
1966
                FundingKey:            ourContribution.MultiSigKey.PubKey,
44✔
1967
                RevocationPoint:       ourContribution.RevocationBasePoint.PubKey,
44✔
1968
                PaymentPoint:          ourContribution.PaymentBasePoint.PubKey,
44✔
1969
                DelayedPaymentPoint:   ourContribution.DelayBasePoint.PubKey,
44✔
1970
                HtlcPoint:             ourContribution.HtlcBasePoint.PubKey,
44✔
1971
                FirstCommitmentPoint:  ourContribution.FirstCommitmentPoint,
44✔
1972
                UpfrontShutdownScript: ourContribution.UpfrontShutdown,
44✔
1973
                ChannelType:           chanType,
44✔
1974
                LeaseExpiry:           msg.LeaseExpiry,
44✔
1975
        }
44✔
1976

44✔
1977
        if commitType.IsTaproot() {
44✔
1978
                fundingAccept.LocalNonce = lnwire.SomeMusig2Nonce(
44✔
1979
                        ourContribution.LocalNonce.PubNonce,
44✔
1980
                )
44✔
1981
        }
44✔
1982

44✔
1983
        if err := peer.SendMessage(true, &fundingAccept); err != nil {
44✔
1984
                log.Errorf("unable to send funding response to peer: %v", err)
44✔
1985
                f.failFundingFlow(peer, cid, err)
44✔
1986
                return
44✔
1987
        }
44✔
1988
}
44✔
1989

44✔
1990
// funderProcessAcceptChannel processes a response to the workflow initiation
44✔
1991
// sent by the remote peer. This message then queues a message with the funding
44✔
1992
// outpoint, and a commitment signature to the remote peer.
44✔
1993
//
49✔
1994
//nolint:funlen
5✔
1995
func (f *Manager) funderProcessAcceptChannel(peer lnpeer.Peer,
5✔
1996
        msg *lnwire.AcceptChannel) {
5✔
1997

5✔
1998
        pendingChanID := msg.PendingChannelID
1999
        peerKey := peer.IdentityKey()
44✔
UNCOV
2000
        var peerKeyBytes []byte
×
UNCOV
2001
        if peerKey != nil {
×
UNCOV
2002
                peerKeyBytes = peerKey.SerializeCompressed()
×
UNCOV
2003
        }
×
2004

2005
        resCtx, err := f.getReservationCtx(peerKey, pendingChanID)
2006
        if err != nil {
2007
                log.Warnf("Can't find reservation (peerKey:%x, chan_id:%v)",
2008
                        peerKeyBytes, pendingChanID)
2009
                return
2010
        }
2011

2012
        // Update the timestamp once the fundingAcceptMsg has been handled.
36✔
2013
        defer resCtx.updateTimestamp()
36✔
2014

36✔
2015
        if resCtx.reservation.State() != lnwallet.SentOpenChannel {
36✔
2016
                return
36✔
2017
        }
72✔
2018

36✔
2019
        log.Infof("Recv'd fundingResponse for pending_id(%x)",
36✔
2020
                pendingChanID[:])
2021

36✔
2022
        // Create the channel identifier.
36✔
UNCOV
2023
        cid := newChanIdentifier(msg.PendingChannelID)
×
UNCOV
2024

×
UNCOV
2025
        // Perform some basic validation of any custom TLV records included.
×
UNCOV
2026
        //
×
2027
        // TODO: Return errors as funding.Error to give context to remote peer?
2028
        if resCtx.channelType != nil {
2029
                // We'll want to quickly check that the ChannelType echoed by
36✔
2030
                // the channel request recipient matches what we proposed.
36✔
2031
                if msg.ChannelType == nil {
36✔
UNCOV
2032
                        err := errors.New("explicit channel type not echoed " +
×
UNCOV
2033
                                "back")
×
2034
                        f.failFundingFlow(peer, cid, err)
2035
                        return
36✔
2036
                }
36✔
2037
                proposedFeatures := lnwire.RawFeatureVector(*resCtx.channelType)
36✔
2038
                ackedFeatures := lnwire.RawFeatureVector(*msg.ChannelType)
36✔
2039
                if !proposedFeatures.Equals(&ackedFeatures) {
36✔
2040
                        err := errors.New("channel type mismatch")
36✔
2041
                        f.failFundingFlow(peer, cid, err)
36✔
2042
                        return
36✔
2043
                }
36✔
2044

43✔
2045
                // We'll want to do the same with the LeaseExpiry if one should
7✔
2046
                // be set.
7✔
2047
                if resCtx.reservation.LeaseExpiry() != 0 {
8✔
2048
                        if msg.LeaseExpiry == nil {
1✔
2049
                                err := errors.New("lease expiry not echoed " +
1✔
2050
                                        "back")
1✔
2051
                                f.failFundingFlow(peer, cid, err)
1✔
2052
                                return
1✔
2053
                        }
6✔
2054
                        if uint32(*msg.LeaseExpiry) !=
6✔
2055
                                resCtx.reservation.LeaseExpiry() {
6✔
2056

×
2057
                                err := errors.New("lease expiry mismatch")
×
2058
                                f.failFundingFlow(peer, cid, err)
×
2059
                                return
×
2060
                        }
2061
                }
2062
        } else if msg.ChannelType != nil {
2063
                // The spec isn't too clear about whether it's okay to set the
9✔
2064
                // channel type in the accept_channel response if we didn't
3✔
2065
                // explicitly set it in the open_channel message. For now, we
×
2066
                // check that it's the same type we'd have arrived through
×
2067
                // implicit negotiation. If it's another type, we fail the flow.
×
2068
                _, implicitCommitType := implicitNegotiateCommitmentType(
×
2069
                        peer.LocalFeatures(), peer.RemoteFeatures(),
×
2070
                )
3✔
2071

3✔
2072
                _, negotiatedCommitType, err := negotiateCommitmentType(
×
2073
                        msg.ChannelType, peer.LocalFeatures(),
×
2074
                        peer.RemoteFeatures(),
×
2075
                )
×
2076
                if err != nil {
×
2077
                        err := errors.New("received unexpected channel type")
2078
                        f.failFundingFlow(peer, cid, err)
29✔
2079
                        return
×
2080
                }
×
UNCOV
2081

×
2082
                if implicitCommitType != negotiatedCommitType {
×
2083
                        err := errors.New("negotiated unexpected channel type")
×
2084
                        f.failFundingFlow(peer, cid, err)
×
2085
                        return
×
2086
                }
×
UNCOV
2087
        }
×
UNCOV
2088

×
UNCOV
2089
        // The required number of confirmations should not be greater than the
×
UNCOV
2090
        // maximum number of confirmations required by the ChainNotifier to
×
UNCOV
2091
        // properly dispatch confirmations.
×
UNCOV
2092
        if msg.MinAcceptDepth > chainntnfs.MaxNumConfs {
×
UNCOV
2093
                err := lnwallet.ErrNumConfsTooLarge(
×
UNCOV
2094
                        msg.MinAcceptDepth, chainntnfs.MaxNumConfs,
×
UNCOV
2095
                )
×
UNCOV
2096
                log.Warnf("Unacceptable channel constraints: %v", err)
×
2097
                f.failFundingFlow(peer, cid, err)
UNCOV
2098
                return
×
UNCOV
2099
        }
×
UNCOV
2100

×
UNCOV
2101
        // Check that zero-conf channels have minimum depth set to 0.
×
UNCOV
2102
        if resCtx.reservation.IsZeroConf() && msg.MinAcceptDepth != 0 {
×
2103
                err = fmt.Errorf("zero-conf channel has min_depth non-zero")
2104
                log.Warn(err)
2105
                f.failFundingFlow(peer, cid, err)
2106
                return
2107
        }
2108

36✔
2109
        // If this is not a zero-conf channel but the peer responded with a
1✔
2110
        // min-depth of zero, we will use our minimum of 1 instead.
1✔
2111
        minDepth := msg.MinAcceptDepth
1✔
2112
        if !resCtx.reservation.IsZeroConf() && minDepth == 0 {
1✔
2113
                log.Infof("Responder to pending_id=%v sent a minimum "+
1✔
2114
                        "confirmation depth of 0 for non-zero-conf channel. "+
1✔
2115
                        "We will use a minimum depth of 1 instead.",
1✔
2116
                        cid.tempChanID)
2117

2118
                minDepth = 1
34✔
2119
        }
×
UNCOV
2120

×
UNCOV
2121
        // We'll also specify the responder's preference for the number of
×
UNCOV
2122
        // required confirmations, and also the set of channel constraints
×
UNCOV
2123
        // they've specified for commitment states we can create.
×
2124
        resCtx.reservation.SetNumConfsRequired(uint16(minDepth))
2125
        bounds := channeldb.ChannelStateBounds{
2126
                ChanReserve:      msg.ChannelReserve,
2127
                MaxPendingAmount: msg.MaxValueInFlight,
34✔
2128
                MinHTLC:          msg.HtlcMinimum,
34✔
UNCOV
2129
                MaxAcceptedHtlcs: msg.MaxAcceptedHTLCs,
×
UNCOV
2130
        }
×
UNCOV
2131
        commitParams := channeldb.CommitmentParams{
×
UNCOV
2132
                DustLimit: msg.DustLimit,
×
UNCOV
2133
                CsvDelay:  msg.CsvDelay,
×
UNCOV
2134
        }
×
UNCOV
2135
        err = resCtx.reservation.CommitConstraints(
×
2136
                &bounds, &commitParams, resCtx.maxLocalCsv, false,
2137
        )
2138
        if err != nil {
2139
                log.Warnf("Unacceptable channel constraints: %v", err)
2140
                f.failFundingFlow(peer, cid, err)
34✔
2141
                return
34✔
2142
        }
34✔
2143

34✔
2144
        cfg := channeldb.ChannelConfig{
34✔
2145
                ChannelStateBounds: channeldb.ChannelStateBounds{
34✔
2146
                        MaxPendingAmount: resCtx.remoteMaxValue,
34✔
2147
                        ChanReserve:      resCtx.remoteChanReserve,
34✔
2148
                        MinHTLC:          resCtx.remoteMinHtlc,
34✔
2149
                        MaxAcceptedHtlcs: resCtx.remoteMaxHtlcs,
34✔
2150
                },
34✔
2151
                CommitmentParams: channeldb.CommitmentParams{
34✔
2152
                        DustLimit: msg.DustLimit,
34✔
2153
                        CsvDelay:  resCtx.remoteCsvDelay,
34✔
2154
                },
35✔
2155
                MultiSigKey: keychain.KeyDescriptor{
1✔
2156
                        PubKey: copyPubKey(msg.FundingKey),
1✔
2157
                },
1✔
2158
                RevocationBasePoint: keychain.KeyDescriptor{
1✔
2159
                        PubKey: copyPubKey(msg.RevocationPoint),
2160
                },
33✔
2161
                PaymentBasePoint: keychain.KeyDescriptor{
33✔
2162
                        PubKey: copyPubKey(msg.PaymentPoint),
33✔
2163
                },
33✔
2164
                DelayBasePoint: keychain.KeyDescriptor{
33✔
2165
                        PubKey: copyPubKey(msg.DelayedPaymentPoint),
33✔
2166
                },
33✔
2167
                HtlcBasePoint: keychain.KeyDescriptor{
33✔
2168
                        PubKey: copyPubKey(msg.HtlcPoint),
33✔
2169
                },
33✔
2170
        }
33✔
2171

33✔
2172
        // The remote node has responded with their portion of the channel
33✔
2173
        // contribution. At this point, we can process their contribution which
33✔
2174
        // allows us to construct and sign both the commitment transaction, and
33✔
2175
        // the funding transaction.
33✔
2176
        remoteContribution := &lnwallet.ChannelContribution{
33✔
2177
                FirstCommitmentPoint: msg.FirstCommitmentPoint,
33✔
2178
                ChannelConfig:        &cfg,
33✔
2179
                UpfrontShutdown:      msg.UpfrontShutdownScript,
33✔
2180
        }
33✔
2181

33✔
2182
        if resCtx.reservation.IsTaproot() {
33✔
2183
                localNonce, err := msg.LocalNonce.UnwrapOrErrV(errNoLocalNonce)
33✔
2184
                if err != nil {
33✔
2185
                        log.Error(errNoLocalNonce)
33✔
2186

33✔
2187
                        f.failFundingFlow(resCtx.peer, cid, errNoLocalNonce)
33✔
2188

33✔
2189
                        return
33✔
2190
                }
33✔
2191

33✔
2192
                remoteContribution.LocalNonce = &musig2.Nonces{
33✔
2193
                        PubNonce: localNonce,
33✔
2194
                }
33✔
2195
        }
33✔
2196

33✔
2197
        err = resCtx.reservation.ProcessContribution(remoteContribution)
33✔
2198

38✔
2199
        // The wallet has detected that a PSBT funding process was requested by
5✔
2200
        // the user and has halted the funding process after negotiating the
5✔
UNCOV
2201
        // multisig keys. We now have everything that is needed for the user to
×
UNCOV
2202
        // start constructing a PSBT that sends to the multisig funding address.
×
UNCOV
2203
        var psbtIntent *chanfunding.PsbtIntent
×
UNCOV
2204
        if psbtErr, ok := err.(*lnwallet.PsbtFundingRequired); ok {
×
UNCOV
2205
                // Return the information that is needed by the user to
×
UNCOV
2206
                // construct the PSBT back to the caller.
×
2207
                addr, amt, packet, err := psbtErr.Intent.FundingParams()
2208
                if err != nil {
5✔
2209
                        log.Errorf("Unable to process PSBT funding params "+
5✔
2210
                                "for contribution from %x: %v", peerKeyBytes,
5✔
2211
                                err)
2212
                        f.failFundingFlow(peer, cid, err)
2213
                        return
33✔
2214
                }
33✔
2215
                var buf bytes.Buffer
33✔
2216
                err = packet.Serialize(&buf)
33✔
2217
                if err != nil {
33✔
2218
                        log.Errorf("Unable to serialize PSBT for "+
33✔
2219
                                "contribution from %x: %v", peerKeyBytes, err)
33✔
2220
                        f.failFundingFlow(peer, cid, err)
36✔
2221
                        return
3✔
2222
                }
3✔
2223
                resCtx.updates <- &lnrpc.OpenStatusUpdate{
3✔
2224
                        PendingChanId: pendingChanID[:],
3✔
UNCOV
2225
                        Update: &lnrpc.OpenStatusUpdate_PsbtFund{
×
UNCOV
2226
                                PsbtFund: &lnrpc.ReadyForPsbtFunding{
×
UNCOV
2227
                                        FundingAddress: addr.EncodeAddress(),
×
UNCOV
2228
                                        FundingAmount:  amt,
×
UNCOV
2229
                                        Psbt:           buf.Bytes(),
×
UNCOV
2230
                                },
×
2231
                        },
3✔
2232
                }
3✔
2233
                psbtIntent = psbtErr.Intent
3✔
UNCOV
2234
        } else if err != nil {
×
2235
                log.Errorf("Unable to process contribution from %x: %v",
×
2236
                        peerKeyBytes, err)
×
2237
                f.failFundingFlow(peer, cid, err)
×
2238
                return
×
2239
        }
3✔
2240

3✔
2241
        log.Infof("pendingChan(%x): remote party proposes num_confs=%v, "+
3✔
2242
                "csv_delay=%v", pendingChanID[:], msg.MinAcceptDepth,
3✔
2243
                msg.CsvDelay)
3✔
2244
        bounds = remoteContribution.ChannelConfig.ChannelStateBounds
3✔
2245
        log.Debugf("Remote party accepted channel state space bounds: %v",
3✔
2246
                lnutils.SpewLogClosure(bounds))
3✔
2247
        commitParams = remoteContribution.ChannelConfig.CommitmentParams
3✔
2248
        log.Debugf("Remote party accepted commitment rendering params: %v",
3✔
2249
                lnutils.SpewLogClosure(commitParams))
3✔
2250

33✔
UNCOV
2251
        // If the user requested funding through a PSBT, we cannot directly
×
UNCOV
2252
        // continue now and need to wait for the fully funded and signed PSBT
×
UNCOV
2253
        // to arrive. To not block any other channels from opening, we wait in
×
UNCOV
2254
        // a separate goroutine.
×
UNCOV
2255
        if psbtIntent != nil {
×
2256
                f.wg.Add(1)
2257
                go func() {
33✔
2258
                        defer f.wg.Done()
33✔
2259

33✔
2260
                        f.waitForPsbt(psbtIntent, resCtx, cid)
33✔
2261
                }()
33✔
2262

33✔
2263
                // With the new goroutine spawned, we can now exit to unblock
33✔
2264
                // the main event loop.
33✔
2265
                return
33✔
2266
        }
33✔
2267

33✔
2268
        // In a normal, non-PSBT funding flow, we can jump directly to the next
33✔
2269
        // step where we expect our contribution to be finalized.
33✔
2270
        f.continueFundingAccept(resCtx, cid)
33✔
2271
}
36✔
2272

3✔
2273
// waitForPsbt blocks until either a signed PSBT arrives, an error occurs or
6✔
2274
// the funding manager shuts down. In the case of a valid PSBT, the funding flow
3✔
2275
// is continued.
3✔
2276
//
3✔
2277
// NOTE: This method must be called as a goroutine.
3✔
2278
func (f *Manager) waitForPsbt(intent *chanfunding.PsbtIntent,
2279
        resCtx *reservationWithCtx, cid *chanIdentifier) {
2280

2281
        // failFlow is a helper that logs an error message with the current
3✔
2282
        // context and then fails the funding flow.
2283
        peerKey := resCtx.peer.IdentityKey()
2284
        failFlow := func(errMsg string, cause error) {
2285
                log.Errorf("Unable to handle funding accept message "+
2286
                        "for peer_key=%x, pending_chan_id=%x: %s: %v",
33✔
2287
                        peerKey.SerializeCompressed(), cid.tempChanID, errMsg,
2288
                        cause)
2289
                f.failFundingFlow(resCtx.peer, cid, cause)
2290
        }
2291

2292
        // We'll now wait until the intent has received the final and complete
2293
        // funding transaction. If the channel is closed without any error being
2294
        // sent, we know everything's going as expected.
2295
        select {
3✔
2296
        case err := <-intent.PsbtReady:
3✔
2297
                switch err {
3✔
2298
                // If the user canceled the funding reservation, we need to
3✔
2299
                // inform the other peer about us canceling the reservation.
3✔
2300
                case chanfunding.ErrUserCanceled:
6✔
2301
                        failFlow("aborting PSBT flow", err)
3✔
2302
                        return
3✔
2303

3✔
2304
                // If the remote canceled the funding reservation, we don't need
3✔
2305
                // to send another fail message. But we want to inform the user
3✔
2306
                // about what happened.
3✔
2307
                case chanfunding.ErrRemoteCanceled:
2308
                        log.Infof("Remote canceled, aborting PSBT flow "+
2309
                                "for peer_key=%x, pending_chan_id=%x",
2310
                                peerKey.SerializeCompressed(), cid.tempChanID)
2311
                        return
3✔
2312

3✔
2313
                // Nil error means the flow continues normally now.
3✔
2314
                case nil:
2315

2316
                // For any other error, we'll fail the funding flow.
3✔
2317
                default:
3✔
2318
                        failFlow("error waiting for PSBT flow", err)
3✔
2319
                        return
2320
                }
2321

2322
                // At this point, we'll see if there's an AuxFundingDesc we
2323
                // need to deliver so the funding process can continue
3✔
2324
                // properly.
3✔
2325
                auxFundingDesc, err := fn.MapOptionZ(
3✔
2326
                        f.cfg.AuxFundingController,
3✔
2327
                        func(c AuxFundingController) AuxFundingDescResult {
3✔
2328
                                return c.DescFromPendingChanID(
2329
                                        cid.tempChanID,
2330
                                        lnwallet.NewAuxChanState(
3✔
2331
                                                resCtx.reservation.ChanState(),
2332
                                        ),
2333
                                        resCtx.reservation.CommitmentKeyRings(),
×
2334
                                        true,
×
2335
                                )
×
2336
                        },
2337
                ).Unpack()
2338
                if err != nil {
2339
                        failFlow("error continuing PSBT flow", err)
2340
                        return
2341
                }
3✔
2342

3✔
2343
                // A non-nil error means we can continue the funding flow.
3✔
UNCOV
2344
                // Notify the wallet so it can prepare everything we need to
×
UNCOV
2345
                // continue.
×
UNCOV
2346
                //
×
UNCOV
2347
                // We'll also pass along the aux funding controller as well,
×
UNCOV
2348
                // which may be used to help process the finalized PSBT.
×
UNCOV
2349
                err = resCtx.reservation.ProcessPsbt(auxFundingDesc)
×
UNCOV
2350
                if err != nil {
×
2351
                        failFlow("error continuing PSBT flow", err)
×
2352
                        return
×
2353
                }
2354

3✔
UNCOV
2355
                // We are now ready to continue the funding flow.
×
UNCOV
2356
                f.continueFundingAccept(resCtx, cid)
×
UNCOV
2357

×
2358
        // Handle a server shutdown as well because the reservation won't
2359
        // survive a restart as it's in memory only.
2360
        case <-f.quit:
2361
                log.Errorf("Unable to handle funding accept message "+
2362
                        "for peer_key=%x, pending_chan_id=%x: funding manager "+
2363
                        "shutting down", peerKey.SerializeCompressed(),
2364
                        cid.tempChanID)
2365
                return
3✔
2366
        }
3✔
UNCOV
2367
}
×
UNCOV
2368

×
UNCOV
2369
// continueFundingAccept continues the channel funding flow once our
×
2370
// contribution is finalized, the channel output is known and the funding
2371
// transaction is signed.
2372
func (f *Manager) continueFundingAccept(resCtx *reservationWithCtx,
3✔
2373
        cid *chanIdentifier) {
2374

2375
        // Now that we have their contribution, we can extract, then send over
UNCOV
2376
        // both the funding out point and our signature for their version of
×
UNCOV
2377
        // the commitment transaction to the remote peer.
×
UNCOV
2378
        outPoint := resCtx.reservation.FundingOutpoint()
×
UNCOV
2379
        _, sig := resCtx.reservation.OurSignatures()
×
UNCOV
2380

×
UNCOV
2381
        // A new channel has almost finished the funding process. In order to
×
2382
        // properly synchronize with the writeHandler goroutine, we add a new
2383
        // channel to the barriers map which will be closed once the channel is
2384
        // fully open.
2385
        channelID := lnwire.NewChanIDFromOutPoint(*outPoint)
2386
        log.Debugf("Creating chan barrier for ChanID(%v)", channelID)
2387

2388
        // The next message that advances the funding flow will reference the
2389
        // channel via its permanent channel ID, so we'll set up this mapping
33✔
2390
        // so we can retrieve the reservation context once we get the
33✔
2391
        // FundingSigned message.
33✔
2392
        f.resMtx.Lock()
33✔
2393
        f.signedReservations[channelID] = cid.tempChanID
33✔
2394
        f.resMtx.Unlock()
33✔
2395

33✔
2396
        log.Infof("Generated ChannelPoint(%v) for pending_id(%x)", outPoint,
33✔
2397
                cid.tempChanID[:])
33✔
2398

33✔
2399
        // Before sending FundingCreated sent, we notify Brontide to keep track
33✔
2400
        // of this pending open channel.
33✔
2401
        err := resCtx.peer.AddPendingChannel(channelID, f.quit)
33✔
2402
        if err != nil {
33✔
2403
                pubKey := resCtx.peer.IdentityKey().SerializeCompressed()
33✔
2404
                log.Errorf("Unable to add pending channel %v with peer %x: %v",
33✔
2405
                        channelID, pubKey, err)
33✔
2406
        }
33✔
2407

33✔
2408
        // Once Brontide is aware of this channel, we need to set it in
33✔
2409
        // chanIdentifier so this channel will be removed from Brontide if the
33✔
2410
        // funding flow fails.
33✔
2411
        cid.setChanID(channelID)
33✔
2412

33✔
2413
        // Send the FundingCreated msg.
33✔
2414
        fundingCreated := &lnwire.FundingCreated{
33✔
2415
                PendingChannelID: cid.tempChanID,
33✔
2416
                FundingPoint:     *outPoint,
33✔
2417
        }
33✔
2418

33✔
UNCOV
2419
        // If this is a taproot channel, then we'll need to populate the musig2
×
UNCOV
2420
        // partial sig field instead of the regular commit sig field.
×
UNCOV
2421
        if resCtx.reservation.IsTaproot() {
×
UNCOV
2422
                partialSig, ok := sig.(*lnwallet.MusigPartialSig)
×
2423
                if !ok {
2424
                        err := fmt.Errorf("expected musig partial sig, got %T",
2425
                                sig)
2426
                        log.Error(err)
2427
                        f.failFundingFlow(resCtx.peer, cid, err)
33✔
2428

33✔
2429
                        return
33✔
2430
                }
33✔
2431

33✔
2432
                fundingCreated.PartialSig = lnwire.MaybePartialSigWithNonce(
33✔
2433
                        partialSig.ToWireSig(),
33✔
2434
                )
33✔
2435
        } else {
33✔
2436
                fundingCreated.CommitSig, err = lnwire.NewSigFromSignature(sig)
33✔
2437
                if err != nil {
38✔
2438
                        log.Errorf("Unable to parse signature: %v", err)
5✔
2439
                        f.failFundingFlow(resCtx.peer, cid, err)
5✔
2440
                        return
×
2441
                }
×
UNCOV
2442
        }
×
UNCOV
2443

×
UNCOV
2444
        resCtx.reservation.SetState(lnwallet.SentFundingCreated)
×
UNCOV
2445

×
UNCOV
2446
        if err := resCtx.peer.SendMessage(true, fundingCreated); err != nil {
×
2447
                log.Errorf("Unable to send funding complete message: %v", err)
2448
                f.failFundingFlow(resCtx.peer, cid, err)
5✔
2449
                return
5✔
2450
        }
5✔
2451
}
31✔
2452

31✔
2453
// fundeeProcessFundingCreated progresses the funding workflow when the daemon
31✔
UNCOV
2454
// is on the responding side of a single funder workflow. Once this message has
×
UNCOV
2455
// been processed, a signature is sent to the remote peer allowing it to
×
UNCOV
2456
// broadcast the funding transaction, progressing the workflow into the final
×
UNCOV
2457
// stage.
×
2458
//
2459
//nolint:funlen
2460
func (f *Manager) fundeeProcessFundingCreated(peer lnpeer.Peer,
33✔
2461
        msg *lnwire.FundingCreated) {
33✔
2462

33✔
UNCOV
2463
        peerKey := peer.IdentityKey()
×
UNCOV
2464
        pendingChanID := msg.PendingChannelID
×
UNCOV
2465

×
UNCOV
2466
        resCtx, err := f.getReservationCtx(peerKey, pendingChanID)
×
2467
        if err != nil {
2468
                log.Warnf("can't find reservation (peer_id:%v, chan_id:%x)",
2469
                        peerKey, pendingChanID[:])
2470
                return
2471
        }
2472

2473
        // The channel initiator has responded with the funding outpoint of the
2474
        // final funding transaction, as well as a signature for our version of
2475
        // the commitment transaction. So at this point, we can validate the
2476
        // initiator's commitment transaction, then send our own if it's valid.
2477
        fundingOut := msg.FundingPoint
31✔
2478
        log.Infof("completing pending_id(%x) with ChannelPoint(%v)",
31✔
2479
                pendingChanID[:], fundingOut)
31✔
2480

31✔
2481
        if resCtx.reservation.State() != lnwallet.SentAcceptChannel {
31✔
2482
                return
31✔
2483
        }
31✔
UNCOV
2484

×
UNCOV
2485
        // Create the channel identifier without setting the active channel ID.
×
UNCOV
2486
        cid := newChanIdentifier(pendingChanID)
×
UNCOV
2487

×
2488
        // For taproot channels, the commit signature is actually the partial
2489
        // signature. Otherwise, we can convert the ECDSA commit signature into
2490
        // our internal input.Signature type.
2491
        var commitSig input.Signature
2492
        if resCtx.reservation.IsTaproot() {
2493
                partialSig, err := msg.PartialSig.UnwrapOrErrV(errNoPartialSig)
31✔
2494
                if err != nil {
31✔
2495
                        f.failFundingFlow(peer, cid, err)
31✔
2496

31✔
2497
                        return
31✔
2498
                }
×
UNCOV
2499

×
2500
                commitSig = new(lnwallet.MusigPartialSig).FromWireSig(
2501
                        &partialSig,
2502
                )
31✔
2503
        } else {
31✔
2504
                commitSig, err = msg.CommitSig.ToSignature()
31✔
2505
                if err != nil {
31✔
2506
                        log.Errorf("unable to parse signature: %v", err)
31✔
2507
                        f.failFundingFlow(peer, cid, err)
31✔
2508
                        return
36✔
2509
                }
5✔
2510
        }
5✔
UNCOV
2511

×
UNCOV
2512
        // At this point, we'll see if there's an AuxFundingDesc we need to
×
UNCOV
2513
        // deliver so the funding process can continue properly.
×
UNCOV
2514
        auxFundingDesc, err := fn.MapOptionZ(
×
2515
                f.cfg.AuxFundingController,
2516
                func(c AuxFundingController) AuxFundingDescResult {
5✔
2517
                        return c.DescFromPendingChanID(
5✔
2518
                                cid.tempChanID, lnwallet.NewAuxChanState(
5✔
2519
                                        resCtx.reservation.ChanState(),
29✔
2520
                                ), resCtx.reservation.CommitmentKeyRings(),
29✔
2521
                                true,
29✔
2522
                        )
×
2523
                },
×
UNCOV
2524
        ).Unpack()
×
UNCOV
2525
        if err != nil {
×
2526
                log.Errorf("error continuing PSBT flow: %v", err)
2527
                f.failFundingFlow(peer, cid, err)
2528
                return
2529
        }
2530

31✔
2531
        // With all the necessary data available, attempt to advance the
31✔
2532
        // funding workflow to the next stage. If this succeeds then the
31✔
UNCOV
2533
        // funding transaction will broadcast after our next message.
×
UNCOV
2534
        // CompleteReservationSingle will also mark the channel as 'IsPending'
×
UNCOV
2535
        // in the database.
×
UNCOV
2536
        //
×
UNCOV
2537
        // We'll also directly pass in the AuxFunding controller as well,
×
UNCOV
2538
        // which may be used by the reservation system to finalize funding our
×
UNCOV
2539
        // side.
×
2540
        completeChan, err := resCtx.reservation.CompleteReservationSingle(
2541
                &fundingOut, commitSig, auxFundingDesc,
31✔
UNCOV
2542
        )
×
UNCOV
2543
        if err != nil {
×
2544
                log.Errorf("unable to complete single reservation: %v", err)
×
2545
                f.failFundingFlow(peer, cid, err)
×
2546
                return
2547
        }
2548

2549
        // Get forwarding policy before deleting the reservation context.
2550
        forwardingPolicy := resCtx.forwardingPolicy
2551

2552
        // The channel is marked IsPending in the database, and can be removed
2553
        // from the set of active reservations.
2554
        f.deleteReservationCtx(peerKey, cid.tempChanID)
2555

2556
        // If something goes wrong before the funding transaction is confirmed,
31✔
2557
        // we use this convenience method to delete the pending OpenChannel
31✔
2558
        // from the database.
31✔
2559
        deleteFromDatabase := func() {
31✔
2560
                localBalance := completeChan.LocalCommitment.LocalBalance.ToSatoshis()
×
2561
                closeInfo := &channeldb.ChannelCloseSummary{
×
2562
                        ChanPoint:               completeChan.FundingOutpoint,
×
2563
                        ChainHash:               completeChan.ChainHash,
×
2564
                        RemotePub:               completeChan.IdentityPub,
2565
                        CloseType:               channeldb.FundingCanceled,
2566
                        Capacity:                completeChan.Capacity,
31✔
2567
                        SettledBalance:          localBalance,
31✔
2568
                        RemoteCurrentRevocation: completeChan.RemoteCurrentRevocation,
31✔
2569
                        RemoteNextRevocation:    completeChan.RemoteNextRevocation,
31✔
2570
                        LocalChanConfig:         completeChan.LocalChanCfg,
31✔
2571
                }
31✔
2572

31✔
2573
                // Close the channel with us as the initiator because we are
31✔
2574
                // deciding to exit the funding flow due to an internal error.
31✔
2575
                if err := completeChan.CloseChannel(
31✔
2576
                        closeInfo, channeldb.ChanStatusLocalCloseInitiator,
×
2577
                ); err != nil {
×
2578
                        log.Errorf("Failed closing channel %v: %v",
×
2579
                                completeChan.FundingOutpoint, err)
×
2580
                }
×
UNCOV
2581
        }
×
UNCOV
2582

×
UNCOV
2583
        // A new channel has almost finished the funding process. In order to
×
UNCOV
2584
        // properly synchronize with the writeHandler goroutine, we add a new
×
UNCOV
2585
        // channel to the barriers map which will be closed once the channel is
×
UNCOV
2586
        // fully open.
×
UNCOV
2587
        channelID := lnwire.NewChanIDFromOutPoint(fundingOut)
×
UNCOV
2588
        log.Debugf("Creating chan barrier for ChanID(%v)", channelID)
×
UNCOV
2589

×
UNCOV
2590
        fundingSigned := &lnwire.FundingSigned{}
×
UNCOV
2591

×
UNCOV
2592
        // For taproot channels, we'll need to send over a partial signature
×
UNCOV
2593
        // that includes the nonce along side the signature.
×
UNCOV
2594
        _, sig := resCtx.reservation.OurSignatures()
×
UNCOV
2595
        if resCtx.reservation.IsTaproot() {
×
UNCOV
2596
                partialSig, ok := sig.(*lnwallet.MusigPartialSig)
×
2597
                if !ok {
2598
                        err := fmt.Errorf("expected musig partial sig, got %T",
2599
                                sig)
2600
                        log.Error(err)
2601
                        f.failFundingFlow(resCtx.peer, cid, err)
2602
                        deleteFromDatabase()
2603

31✔
2604
                        return
31✔
2605
                }
31✔
2606

31✔
2607
                fundingSigned.PartialSig = lnwire.MaybePartialSigWithNonce(
31✔
2608
                        partialSig.ToWireSig(),
31✔
2609
                )
31✔
2610
        } else {
31✔
2611
                fundingSigned.CommitSig, err = lnwire.NewSigFromSignature(sig)
36✔
2612
                if err != nil {
5✔
2613
                        log.Errorf("unable to parse signature: %v", err)
5✔
2614
                        f.failFundingFlow(peer, cid, err)
×
2615
                        deleteFromDatabase()
×
2616

×
2617
                        return
×
2618
                }
×
UNCOV
2619
        }
×
UNCOV
2620

×
UNCOV
2621
        // Before sending FundingSigned, we notify Brontide first to keep track
×
2622
        // of this pending open channel.
2623
        if err := peer.AddPendingChannel(channelID, f.quit); err != nil {
5✔
2624
                pubKey := peer.IdentityKey().SerializeCompressed()
5✔
2625
                log.Errorf("Unable to add pending channel %v with peer %x: %v",
5✔
2626
                        cid.chanID, pubKey, err)
29✔
2627
        }
29✔
2628

29✔
UNCOV
2629
        // Once Brontide is aware of this channel, we need to set it in
×
UNCOV
2630
        // chanIdentifier so this channel will be removed from Brontide if the
×
UNCOV
2631
        // funding flow fails.
×
UNCOV
2632
        cid.setChanID(channelID)
×
UNCOV
2633

×
UNCOV
2634
        fundingSigned.ChanID = cid.chanID
×
2635

2636
        log.Infof("sending FundingSigned for pending_id(%x) over "+
2637
                "ChannelPoint(%v)", pendingChanID[:], fundingOut)
2638

2639
        // With their signature for our version of the commitment transaction
31✔
UNCOV
2640
        // verified, we can now send over our signature to the remote peer.
×
UNCOV
2641
        if err := peer.SendMessage(true, fundingSigned); err != nil {
×
2642
                log.Errorf("unable to send FundingSigned message: %v", err)
×
2643
                f.failFundingFlow(peer, cid, err)
×
2644
                deleteFromDatabase()
2645
                return
2646
        }
2647

2648
        // With a permanent channel id established we can save the respective
31✔
2649
        // forwarding policy in the database. In the channel announcement phase
31✔
2650
        // this forwarding policy is retrieved and applied.
31✔
2651
        err = f.saveInitialForwardingPolicy(cid.chanID, &forwardingPolicy)
31✔
2652
        if err != nil {
31✔
2653
                log.Errorf("Unable to store the forwarding policy: %v", err)
31✔
2654
        }
31✔
2655

31✔
2656
        // Now that we've sent over our final signature for this channel, we'll
31✔
2657
        // send it to the ChainArbitrator so it can watch for any on-chain
31✔
UNCOV
2658
        // actions during this final confirmation stage.
×
UNCOV
2659
        if err := f.cfg.WatchNewChannel(completeChan, peerKey); err != nil {
×
2660
                log.Errorf("Unable to send new ChannelPoint(%v) for "+
×
2661
                        "arbitration: %v", fundingOut, err)
×
2662
        }
×
2663

2664
        // Create an entry in the local discovery map so we can ensure that we
2665
        // process the channel confirmation fully before we receive a
2666
        // channel_ready message.
2667
        f.localDiscoverySignals.Store(cid.chanID, make(chan struct{}))
31✔
2668

31✔
UNCOV
2669
        // Inform the ChannelNotifier that the channel has entered
×
UNCOV
2670
        // pending open state.
×
2671
        f.cfg.NotifyPendingOpenChannelEvent(
2672
                fundingOut, completeChan, completeChan.IdentityPub,
2673
        )
2674

2675
        // At this point we have sent our last funding message to the
31✔
UNCOV
2676
        // initiating peer before the funding transaction will be broadcast.
×
UNCOV
2677
        // With this last message, our job as the responder is now complete.
×
UNCOV
2678
        // We'll wait for the funding transaction to reach the specified number
×
2679
        // of confirmations, then start normal operations.
2680
        //
2681
        // When we get to this point we have sent the signComplete message to
2682
        // the channel funder, and BOLT#2 specifies that we MUST remember the
2683
        // channel for reconnection. The channel is already marked
31✔
2684
        // as pending in the database, so in case of a disconnect or restart,
31✔
2685
        // we will continue waiting for the confirmation the next time we start
31✔
2686
        // the funding manager. In case the funding transaction never appears
31✔
2687
        // on the blockchain, we must forget this channel. We therefore
31✔
2688
        // completely forget about this channel if we haven't seen the funding
31✔
2689
        // transaction in 288 blocks (~ 48 hrs), by canceling the reservation
31✔
2690
        // and canceling the wait for the funding confirmation.
31✔
2691
        f.wg.Add(1)
31✔
2692
        go f.advanceFundingState(completeChan, pendingChanID, nil)
31✔
2693
}
31✔
2694

31✔
2695
// funderProcessFundingSigned processes the final message received in a single
31✔
2696
// funder workflow. Once this message is processed, the funding transaction is
31✔
2697
// broadcast. Once the funding transaction reaches a sufficient number of
31✔
2698
// confirmations, a message is sent to the responding peer along with a compact
31✔
2699
// encoding of the location of the channel within the blockchain.
31✔
2700
func (f *Manager) funderProcessFundingSigned(peer lnpeer.Peer,
31✔
2701
        msg *lnwire.FundingSigned) {
31✔
2702

31✔
2703
        // As the funding signed message will reference the reservation by its
31✔
2704
        // permanent channel ID, we'll need to perform an intermediate look up
31✔
2705
        // before we can obtain the reservation.
31✔
2706
        f.resMtx.Lock()
31✔
2707
        pendingChanID, ok := f.signedReservations[msg.ChanID]
31✔
2708
        delete(f.signedReservations, msg.ChanID)
31✔
2709
        f.resMtx.Unlock()
2710

2711
        // Create the channel identifier and set the channel ID.
2712
        //
2713
        // NOTE: we may get an empty pending channel ID here if the key cannot
2714
        // be found, which means when we cancel the reservation context in
2715
        // `failFundingFlow`, we will get an error. In this case, we will send
2716
        // an error msg to our peer using the active channel ID.
2717
        //
31✔
2718
        // TODO(yy): refactor the funding flow to fix this case.
31✔
2719
        cid := newChanIdentifier(pendingChanID)
31✔
2720
        cid.setChanID(msg.ChanID)
31✔
2721

31✔
2722
        // If the pending channel ID is not found, fail the funding flow.
31✔
2723
        if !ok {
31✔
2724
                // NOTE: we directly overwrite the pending channel ID here for
31✔
2725
                // this rare case since we don't have a valid pending channel
31✔
2726
                // ID.
31✔
2727
                cid.tempChanID = msg.ChanID
31✔
2728

31✔
2729
                err := fmt.Errorf("unable to find signed reservation for "+
31✔
2730
                        "chan_id=%x", msg.ChanID)
31✔
2731
                log.Warnf(err.Error())
31✔
2732
                f.failFundingFlow(peer, cid, err)
31✔
2733
                return
31✔
2734
        }
31✔
2735

31✔
2736
        peerKey := peer.IdentityKey()
31✔
2737
        resCtx, err := f.getReservationCtx(peerKey, pendingChanID)
31✔
2738
        if err != nil {
31✔
2739
                log.Warnf("Unable to find reservation (peer_id:%v, "+
31✔
2740
                        "chan_id:%x)", peerKey, pendingChanID[:])
×
2741
                // TODO: add ErrChanNotFound?
×
2742
                f.failFundingFlow(peer, cid, err)
×
2743
                return
×
2744
        }
×
UNCOV
2745

×
UNCOV
2746
        if resCtx.reservation.State() != lnwallet.SentFundingCreated {
×
2747
                err := fmt.Errorf("unable to find reservation for chan_id=%x",
×
2748
                        msg.ChanID)
×
2749
                f.failFundingFlow(peer, cid, err)
×
2750

×
2751
                return
2752
        }
31✔
2753

31✔
2754
        // Create an entry in the local discovery map so we can ensure that we
31✔
UNCOV
2755
        // process the channel confirmation fully before we receive a
×
UNCOV
2756
        // channel_ready message.
×
UNCOV
2757
        fundingPoint := resCtx.reservation.FundingOutpoint()
×
UNCOV
2758
        permChanID := lnwire.NewChanIDFromOutPoint(*fundingPoint)
×
UNCOV
2759
        f.localDiscoverySignals.Store(permChanID, make(chan struct{}))
×
UNCOV
2760

×
2761
        // We have to store the forwardingPolicy before the reservation context
2762
        // is deleted. The policy will then be read and applied in
31✔
UNCOV
2763
        // newChanAnnouncement.
×
UNCOV
2764
        err = f.saveInitialForwardingPolicy(
×
UNCOV
2765
                permChanID, &resCtx.forwardingPolicy,
×
UNCOV
2766
        )
×
UNCOV
2767
        if err != nil {
×
2768
                log.Errorf("Unable to store the forwarding policy: %v", err)
×
2769
        }
2770

2771
        // For taproot channels, the commit signature is actually the partial
2772
        // signature. Otherwise, we can convert the ECDSA commit signature into
2773
        // our internal input.Signature type.
31✔
2774
        var commitSig input.Signature
31✔
2775
        if resCtx.reservation.IsTaproot() {
31✔
2776
                partialSig, err := msg.PartialSig.UnwrapOrErrV(errNoPartialSig)
31✔
2777
                if err != nil {
31✔
2778
                        f.failFundingFlow(peer, cid, err)
31✔
2779

31✔
2780
                        return
31✔
2781
                }
31✔
2782

31✔
2783
                commitSig = new(lnwallet.MusigPartialSig).FromWireSig(
31✔
UNCOV
2784
                        &partialSig,
×
UNCOV
2785
                )
×
2786
        } else {
2787
                commitSig, err = msg.CommitSig.ToSignature()
2788
                if err != nil {
2789
                        log.Errorf("unable to parse signature: %v", err)
2790
                        f.failFundingFlow(peer, cid, err)
31✔
2791
                        return
36✔
2792
                }
5✔
2793
        }
5✔
UNCOV
2794

×
UNCOV
2795
        completeChan, err := resCtx.reservation.CompleteReservation(
×
UNCOV
2796
                nil, commitSig,
×
UNCOV
2797
        )
×
2798
        if err != nil {
2799
                log.Errorf("Unable to complete reservation sign "+
5✔
2800
                        "complete: %v", err)
5✔
2801
                f.failFundingFlow(peer, cid, err)
5✔
2802
                return
29✔
2803
        }
29✔
2804

29✔
UNCOV
2805
        // The channel is now marked IsPending in the database, and we can
×
UNCOV
2806
        // delete it from our set of active reservations.
×
UNCOV
2807
        f.deleteReservationCtx(peerKey, pendingChanID)
×
UNCOV
2808

×
2809
        // Broadcast the finalized funding transaction to the network, but only
2810
        // if we actually have the funding transaction.
2811
        if completeChan.ChanType.HasFundingTx() {
31✔
2812
                fundingTx := completeChan.FundingTxn
31✔
2813
                var fundingTxBuf bytes.Buffer
31✔
2814
                if err := fundingTx.Serialize(&fundingTxBuf); err != nil {
31✔
2815
                        log.Errorf("Unable to serialize funding "+
×
2816
                                "transaction %v: %v", fundingTx.TxHash(), err)
×
2817

×
2818
                        // Clear the buffer of any bytes that were written
×
2819
                        // before the serialization error to prevent logging an
×
2820
                        // incomplete transaction.
2821
                        fundingTxBuf.Reset()
2822
                }
2823

31✔
2824
                log.Infof("Broadcasting funding tx for ChannelPoint(%v): %x",
31✔
2825
                        completeChan.FundingOutpoint, fundingTxBuf.Bytes())
31✔
2826

31✔
2827
                // Set a nil short channel ID at this stage because we do not
61✔
2828
                // know it until our funding tx confirms.
30✔
2829
                label := labels.MakeLabel(
30✔
2830
                        labels.LabelTypeChannelOpen, nil,
30✔
UNCOV
2831
                )
×
UNCOV
2832

×
UNCOV
2833
                err = f.cfg.PublishTransaction(fundingTx, label)
×
UNCOV
2834
                if err != nil {
×
2835
                        log.Errorf("Unable to broadcast funding tx %x for "+
×
2836
                                "ChannelPoint(%v): %v", fundingTxBuf.Bytes(),
×
2837
                                completeChan.FundingOutpoint, err)
×
2838

×
2839
                        // We failed to broadcast the funding transaction, but
2840
                        // watch the channel regardless, in case the
30✔
2841
                        // transaction made it to the network. We will retry
30✔
2842
                        // broadcast at startup.
30✔
2843
                        //
30✔
2844
                        // TODO(halseth): retry more often? Handle with CPFP?
30✔
2845
                        // Just delete from the DB?
30✔
2846
                }
30✔
2847
        }
30✔
2848

30✔
2849
        // Before we proceed, if we have a funding hook that wants a
30✔
2850
        // notification that it's safe to broadcast the funding transaction,
30✔
UNCOV
2851
        // then we'll send that now.
×
UNCOV
2852
        err = fn.MapOptionZ(
×
UNCOV
2853
                f.cfg.AuxFundingController,
×
UNCOV
2854
                func(controller AuxFundingController) error {
×
2855
                        return controller.ChannelFinalized(cid.tempChanID)
×
2856
                },
×
UNCOV
2857
        )
×
UNCOV
2858
        if err != nil {
×
2859
                log.Errorf("Failed to inform aux funding controller about "+
×
2860
                        "ChannelPoint(%v) being finalized: %v", fundingPoint,
×
2861
                        err)
×
2862
        }
×
2863

2864
        // Now that we have a finalized reservation for this funding flow,
2865
        // we'll send the to be active channel to the ChainArbitrator so it can
2866
        // watch for any on-chain actions before the channel has fully
2867
        // confirmed.
2868
        if err := f.cfg.WatchNewChannel(completeChan, peerKey); err != nil {
31✔
2869
                log.Errorf("Unable to send new ChannelPoint(%v) for "+
31✔
2870
                        "arbitration: %v", fundingPoint, err)
31✔
2871
        }
×
UNCOV
2872

×
2873
        log.Infof("Finalizing pending_id(%x) over ChannelPoint(%v), "+
2874
                "waiting for channel open on-chain", pendingChanID[:],
31✔
UNCOV
2875
                fundingPoint)
×
UNCOV
2876

×
UNCOV
2877
        // Send an update to the upstream client that the negotiation process
×
UNCOV
2878
        // is over.
×
2879
        upd := &lnrpc.OpenStatusUpdate{
2880
                Update: &lnrpc.OpenStatusUpdate_ChanPending{
2881
                        ChanPending: &lnrpc.PendingUpdate{
2882
                                Txid:        fundingPoint.Hash[:],
2883
                                OutputIndex: fundingPoint.Index,
2884
                        },
31✔
UNCOV
2885
                },
×
UNCOV
2886
                PendingChanId: pendingChanID[:],
×
UNCOV
2887
        }
×
2888

2889
        select {
31✔
2890
        case resCtx.updates <- upd:
31✔
2891
                // Inform the ChannelNotifier that the channel has entered
31✔
2892
                // pending open state.
31✔
2893
                f.cfg.NotifyPendingOpenChannelEvent(
31✔
2894
                        *fundingPoint, completeChan, completeChan.IdentityPub,
31✔
2895
                )
31✔
2896

31✔
2897
        case <-f.quit:
31✔
2898
                return
31✔
2899
        }
31✔
2900

31✔
2901
        // At this point we have broadcast the funding transaction and done all
31✔
2902
        // necessary processing.
31✔
2903
        f.wg.Add(1)
31✔
2904
        go f.advanceFundingState(completeChan, pendingChanID, resCtx.updates)
31✔
2905
}
31✔
2906

31✔
2907
// confirmedChannel wraps a confirmed funding transaction, as well as the short
31✔
2908
// channel ID which identifies that channel into a single struct. We'll use
31✔
2909
// this to pass around the final state of a channel after it has been
31✔
2910
// confirmed.
31✔
2911
type confirmedChannel struct {
31✔
2912
        // shortChanID expresses where in the block the funding transaction was
UNCOV
2913
        // located.
×
UNCOV
2914
        shortChanID lnwire.ShortChannelID
×
2915

2916
        // fundingTx is the funding transaction that created the channel.
2917
        fundingTx *wire.MsgTx
2918
}
2919

31✔
2920
// fundingTimeout is called when callers of waitForFundingWithTimeout receive
31✔
2921
// an ErrConfirmationTimeout. It is used to clean-up channel state and mark the
2922
// channel as closed. The error is only returned for the responder of the
2923
// channel flow.
2924
func (f *Manager) fundingTimeout(c *channeldb.OpenChannel,
2925
        pendingID PendingChanID) error {
2926

2927
        // We'll get a timeout if the number of blocks mined since the channel
2928
        // was initiated reaches MaxWaitNumBlocksFundingConf and we are not the
2929
        // channel initiator.
2930
        localBalance := c.LocalCommitment.LocalBalance.ToSatoshis()
2931
        closeInfo := &channeldb.ChannelCloseSummary{
2932
                ChainHash:               c.ChainHash,
2933
                ChanPoint:               c.FundingOutpoint,
2934
                RemotePub:               c.IdentityPub,
2935
                Capacity:                c.Capacity,
2936
                SettledBalance:          localBalance,
2937
                CloseType:               channeldb.FundingCanceled,
2938
                RemoteCurrentRevocation: c.RemoteCurrentRevocation,
2939
                RemoteNextRevocation:    c.RemoteNextRevocation,
2940
                LocalChanConfig:         c.LocalChanCfg,
2941
        }
5✔
2942

5✔
2943
        // Close the channel with us as the initiator because we are timing the
5✔
2944
        // channel out.
5✔
2945
        if err := c.CloseChannel(
5✔
2946
                closeInfo, channeldb.ChanStatusLocalCloseInitiator,
5✔
2947
        ); err != nil {
5✔
2948
                return fmt.Errorf("failed closing channel %v: %w",
5✔
2949
                        c.FundingOutpoint, err)
5✔
2950
        }
5✔
2951

5✔
2952
        // Notify other subsystems about the funding timeout.
5✔
2953
        f.cfg.NotifyFundingTimeout(c.FundingOutpoint, c.IdentityPub)
5✔
2954

5✔
2955
        timeoutErr := fmt.Errorf("timeout waiting for funding tx (%v) to "+
5✔
2956
                "confirm", c.FundingOutpoint)
5✔
2957

5✔
2958
        // When the peer comes online, we'll notify it that we are now
5✔
2959
        // considering the channel flow canceled.
5✔
2960
        f.wg.Add(1)
5✔
2961
        go func() {
5✔
2962
                defer f.wg.Done()
5✔
2963

5✔
UNCOV
2964
                peer, err := f.waitForPeerOnline(c.IdentityPub)
×
UNCOV
2965
                switch err {
×
UNCOV
2966
                // We're already shutting down, so we can just return.
×
2967
                case ErrFundingManagerShuttingDown:
2968
                        return
2969

5✔
2970
                // nil error means we continue on.
5✔
2971
                case nil:
5✔
2972

5✔
2973
                // For unexpected errors, we print the error and still try to
5✔
2974
                // fail the funding flow.
5✔
2975
                default:
5✔
2976
                        log.Errorf("Unexpected error while waiting for peer "+
5✔
2977
                                "to come online: %v", err)
10✔
2978
                }
5✔
2979

5✔
2980
                // Create channel identifier and set the channel ID.
5✔
2981
                cid := newChanIdentifier(pendingID)
5✔
2982
                cid.setChanID(lnwire.NewChanIDFromOutPoint(c.FundingOutpoint))
UNCOV
2983

×
UNCOV
2984
                // TODO(halseth): should this send be made
×
2985
                // reliable?
2986

2987
                // The reservation won't exist at this point, but we'll send an
5✔
2988
                // Error message over anyways with ChanID set to pendingID.
2989
                f.failFundingFlow(peer, cid, timeoutErr)
2990
        }()
UNCOV
2991

×
UNCOV
2992
        return timeoutErr
×
UNCOV
2993
}
×
2994

2995
// waitForFundingWithTimeout is a wrapper around waitForFundingConfirmation and
2996
// waitForTimeout that will return ErrConfirmationTimeout if we are not the
2997
// channel initiator and the MaxWaitNumBlocksFundingConf has passed from the
5✔
2998
// funding broadcast height. In case of confirmation, the short channel ID of
5✔
2999
// the channel and the funding transaction will be returned.
5✔
3000
func (f *Manager) waitForFundingWithTimeout(
5✔
3001
        ch *channeldb.OpenChannel) (*confirmedChannel, error) {
5✔
3002

5✔
3003
        confChan := make(chan *confirmedChannel)
5✔
3004
        timeoutChan := make(chan error, 1)
5✔
3005
        cancelChan := make(chan struct{})
5✔
3006

3007
        f.wg.Add(1)
3008
        go f.waitForFundingConfirmation(ch, cancelChan, confChan)
5✔
3009

3010
        // If we are not the initiator, we have no money at stake and will
3011
        // timeout waiting for the funding transaction to confirm after a
3012
        // while.
3013
        if !ch.IsInitiator && !ch.IsZeroConf() {
3014
                f.wg.Add(1)
3015
                go f.waitForTimeout(ch, cancelChan, timeoutChan)
3016
        }
3017
        defer close(cancelChan)
62✔
3018

62✔
3019
        select {
62✔
3020
        case err := <-timeoutChan:
62✔
3021
                if err != nil {
62✔
3022
                        return nil, err
62✔
3023
                }
62✔
3024
                return nil, ErrConfirmationTimeout
62✔
3025

62✔
3026
        case <-f.quit:
62✔
3027
                // The fundingManager is shutting down, and will resume wait on
62✔
3028
                // startup.
62✔
3029
                return nil, ErrFundingManagerShuttingDown
91✔
3030

29✔
3031
        case confirmedChannel, ok := <-confChan:
29✔
3032
                if !ok {
29✔
3033
                        return nil, fmt.Errorf("waiting for funding" +
62✔
3034
                                "confirmation failed")
62✔
3035
                }
62✔
3036
                return confirmedChannel, nil
5✔
3037
        }
5✔
UNCOV
3038
}
×
UNCOV
3039

×
3040
// makeFundingScript re-creates the funding script for the funding transaction
5✔
3041
// of the target channel.
3042
func makeFundingScript(channel *channeldb.OpenChannel) ([]byte, error) {
26✔
3043
        localKey := channel.LocalChanCfg.MultiSigKey.PubKey
26✔
3044
        remoteKey := channel.RemoteChanCfg.MultiSigKey.PubKey
26✔
3045

26✔
3046
        if channel.ChanType.IsTaproot() {
3047
                pkScript, _, err := input.GenTaprootFundingScript(
37✔
3048
                        localKey, remoteKey, int64(channel.Capacity),
37✔
UNCOV
3049
                        channel.TapscriptRoot,
×
UNCOV
3050
                )
×
UNCOV
3051
                if err != nil {
×
3052
                        return nil, err
37✔
3053
                }
3054

3055
                return pkScript, nil
3056
        }
3057

3058
        multiSigScript, err := input.GenMultiSigScript(
82✔
3059
                localKey.SerializeCompressed(),
82✔
3060
                remoteKey.SerializeCompressed(),
82✔
3061
        )
82✔
3062
        if err != nil {
90✔
3063
                return nil, err
8✔
3064
        }
8✔
3065

8✔
3066
        return input.WitnessScriptHash(multiSigScript)
8✔
3067
}
8✔
UNCOV
3068

×
UNCOV
3069
// waitForFundingConfirmation handles the final stages of the channel funding
×
3070
// process once the funding transaction has been broadcast. The primary
3071
// function of waitForFundingConfirmation is to wait for blockchain
8✔
3072
// confirmation, and then to notify the other systems that must be notified
3073
// when a channel has become active for lightning transactions. It also updates
3074
// the channel’s opening transaction block height in the database.
77✔
3075
// The wait can be canceled by closing the cancelChan. In case of success,
77✔
3076
// a *lnwire.ShortChannelID will be passed to confChan.
77✔
3077
//
77✔
3078
// NOTE: This MUST be run as a goroutine.
77✔
UNCOV
3079
func (f *Manager) waitForFundingConfirmation(
×
UNCOV
3080
        completeChan *channeldb.OpenChannel, cancelChan <-chan struct{},
×
3081
        confChan chan<- *confirmedChannel) {
3082

77✔
3083
        defer f.wg.Done()
3084
        defer close(confChan)
3085

3086
        // Register with the ChainNotifier for a notification once the funding
3087
        // transaction reaches `numConfs` confirmations.
3088
        txid := completeChan.FundingOutpoint.Hash
3089
        fundingScript, err := makeFundingScript(completeChan)
3090
        if err != nil {
3091
                log.Errorf("unable to create funding script for "+
3092
                        "ChannelPoint(%v): %v", completeChan.FundingOutpoint,
3093
                        err)
3094
                return
3095
        }
3096
        numConfs := uint32(completeChan.NumConfsRequired)
3097

62✔
3098
        // If the underlying channel is a zero-conf channel, we'll set numConfs
62✔
3099
        // to 6, since it will be zero here.
62✔
3100
        if completeChan.IsZeroConf() {
62✔
3101
                numConfs = 6
62✔
3102
        }
62✔
3103

62✔
3104
        confNtfn, err := f.cfg.Notifier.RegisterConfirmationsNtfn(
62✔
3105
                &txid, fundingScript, numConfs,
62✔
3106
                completeChan.BroadcastHeight(),
62✔
UNCOV
3107
        )
×
UNCOV
3108
        if err != nil {
×
3109
                log.Errorf("Unable to register for confirmation of "+
×
3110
                        "ChannelPoint(%v): %v", completeChan.FundingOutpoint,
×
3111
                        err)
×
3112
                return
62✔
3113
        }
62✔
3114

62✔
3115
        log.Infof("Waiting for funding tx (%v) to reach %v confirmations",
62✔
3116
                txid, numConfs)
71✔
3117

9✔
3118
        // Wait until the specified number of confirmations has been reached,
9✔
3119
        // we get a cancel signal, or the wallet signals a shutdown.
3120
        for {
62✔
3121
                select {
62✔
3122
                case updDetails, ok := <-confNtfn.Updates:
62✔
3123
                        if !ok {
62✔
3124
                                log.Warnf("ChainNotifier shutting down, "+
62✔
3125
                                        "cannot process updates for "+
×
3126
                                        "ChannelPoint(%v)",
×
3127
                                        completeChan.FundingOutpoint)
×
3128

×
3129
                                return
×
3130
                        }
3131

62✔
3132
                        log.Debugf("funding tx %s received confirmation in "+
62✔
3133
                                "block %d, %d confirmations left", txid,
62✔
3134
                                updDetails.BlockHeight, updDetails.NumConfsLeft)
62✔
3135

62✔
3136
                        // Only update the ConfirmationHeight the first time a
151✔
3137
                        // confirmation is received, since on subsequent
89✔
3138
                        // confirmations the block height will remain the same.
28✔
3139
                        if completeChan.ConfirmationHeight == 0 {
28✔
UNCOV
3140
                                err := completeChan.MarkConfirmationHeight(
×
UNCOV
3141
                                        updDetails.BlockHeight,
×
UNCOV
3142
                                )
×
UNCOV
3143
                                if err != nil {
×
3144
                                        log.Errorf("failed to update "+
×
3145
                                                "confirmed state for "+
×
3146
                                                "ChannelPoint(%v): %v",
×
3147
                                                completeChan.FundingOutpoint,
3148
                                                err)
28✔
3149

28✔
3150
                                        return
28✔
3151
                                }
28✔
3152
                        }
28✔
3153

28✔
3154
                case _, ok := <-confNtfn.NegativeConf:
28✔
3155
                        if !ok {
56✔
3156
                                log.Warnf("ChainNotifier shutting down, "+
28✔
3157
                                        "cannot track negative confirmations "+
28✔
3158
                                        "for ChannelPoint(%v)",
28✔
3159
                                        completeChan.FundingOutpoint)
28✔
3160

×
3161
                                return
×
3162
                        }
×
UNCOV
3163

×
UNCOV
3164
                        log.Warnf("funding tx %s was reorged out; channel "+
×
UNCOV
3165
                                "point: %s", txid, completeChan.FundingOutpoint)
×
UNCOV
3166

×
UNCOV
3167
                        // Reset the confirmation height to 0 because the
×
3168
                        // funding transaction was reorged out.
3169
                        err := completeChan.MarkConfirmationHeight(uint32(0))
3170
                        if err != nil {
4✔
3171
                                log.Errorf("failed to update state for "+
4✔
3172
                                        "ChannelPoint(%v): %v",
×
3173
                                        completeChan.FundingOutpoint, err)
×
3174

×
3175
                                return
×
3176
                        }
×
UNCOV
3177

×
UNCOV
3178
                case confDetails, ok := <-confNtfn.Confirmed:
×
3179
                        if !ok {
3180
                                log.Warnf("ChainNotifier shutting down, "+
4✔
3181
                                        "cannot complete funding flow for "+
4✔
3182
                                        "ChannelPoint(%v)",
4✔
3183
                                        completeChan.FundingOutpoint)
4✔
3184

4✔
3185
                                return
4✔
3186
                        }
4✔
UNCOV
3187

×
UNCOV
3188
                        log.Debugf("funding tx %s for ChannelPoint(%v) "+
×
UNCOV
3189
                                "confirmed in block %d", txid,
×
UNCOV
3190
                                completeChan.FundingOutpoint,
×
UNCOV
3191
                                confDetails.BlockHeight)
×
UNCOV
3192

×
3193
                        // In the case of requiring a single confirmation, it
3194
                        // can happen that the `Confirmed` channel is read
37✔
3195
                        // from first, in which case the confirmation height
37✔
UNCOV
3196
                        // will not be set. If this happens, we take the
×
UNCOV
3197
                        // confirmation height from the `Confirmed` channel.
×
UNCOV
3198
                        if completeChan.ConfirmationHeight == 0 {
×
UNCOV
3199
                                err := completeChan.MarkConfirmationHeight(
×
UNCOV
3200
                                        confDetails.BlockHeight,
×
UNCOV
3201
                                )
×
UNCOV
3202
                                if err != nil {
×
3203
                                        log.Errorf("failed to update "+
3204
                                                "confirmed state for "+
37✔
3205
                                                "ChannelPoint(%v): %v",
37✔
3206
                                                completeChan.FundingOutpoint,
37✔
3207
                                                err)
37✔
3208

37✔
3209
                                        return
37✔
3210
                                }
37✔
3211
                        }
37✔
3212

37✔
3213
                        err := f.handleConfirmation(
37✔
3214
                                confDetails, completeChan, confChan,
50✔
3215
                        )
13✔
3216
                        if err != nil {
13✔
3217
                                log.Errorf("Error handling confirmation for "+
13✔
3218
                                        "ChannelPoint(%v), txid=%v: %v",
13✔
3219
                                        completeChan.FundingOutpoint, txid, err)
×
3220
                        }
×
UNCOV
3221

×
UNCOV
3222
                        return
×
UNCOV
3223

×
UNCOV
3224
                case <-cancelChan:
×
UNCOV
3225
                        log.Warnf("canceled waiting for funding confirmation, "+
×
UNCOV
3226
                                "stopping funding flow for ChannelPoint(%v)",
×
3227
                                completeChan.FundingOutpoint)
3228

3229
                        return
37✔
3230

37✔
3231
                case <-f.quit:
37✔
3232
                        log.Warnf("fundingManager shutting down, stopping "+
37✔
UNCOV
3233
                                "funding flow for ChannelPoint(%v)",
×
UNCOV
3234
                                completeChan.FundingOutpoint)
×
UNCOV
3235

×
UNCOV
3236
                        return
×
3237
                }
3238
        }
37✔
3239
}
3240

5✔
3241
// handleConfirmation is a helper function that constructs a ShortChannelID
5✔
3242
// based on the confirmation details and sends this information, along with the
5✔
3243
// funding transaction, to the provided confirmation channel.
5✔
3244
func (f *Manager) handleConfirmation(confDetails *chainntnfs.TxConfirmation,
5✔
3245
        completeChan *channeldb.OpenChannel,
5✔
3246
        confChan chan<- *confirmedChannel) error {
3247

26✔
3248
        fundingPoint := completeChan.FundingOutpoint
26✔
3249
        log.Infof("ChannelPoint(%v) is now active: ChannelID(%v)",
26✔
3250
                fundingPoint, lnwire.NewChanIDFromOutPoint(fundingPoint))
26✔
3251

26✔
3252
        // With the block height and the transaction index known, we can
26✔
3253
        // construct the compact chanID which is used on the network to unique
3254
        // identify channels.
3255
        shortChanID := lnwire.ShortChannelID{
3256
                BlockHeight: confDetails.BlockHeight,
3257
                TxIndex:     confDetails.TxIndex,
3258
                TxPosition:  uint16(fundingPoint.Index),
3259
        }
3260

3261
        select {
3262
        case confChan <- &confirmedChannel{
37✔
3263
                shortChanID: shortChanID,
37✔
3264
                fundingTx:   confDetails.Tx,
37✔
3265
        }:
37✔
3266
        case <-f.quit:
37✔
3267
                return fmt.Errorf("manager shutting down")
37✔
3268
        }
37✔
3269

37✔
3270
        return nil
37✔
3271
}
37✔
3272

37✔
3273
// waitForTimeout will close the timeout channel if MaxWaitNumBlocksFundingConf
37✔
3274
// has passed from the broadcast height of the given channel. In case of error,
37✔
3275
// the error is sent on timeoutChan. The wait can be canceled by closing the
37✔
3276
// cancelChan.
37✔
3277
//
37✔
3278
// NOTE: timeoutChan MUST be buffered.
3279
// NOTE: This MUST be run as a goroutine.
3280
func (f *Manager) waitForTimeout(completeChan *channeldb.OpenChannel,
3281
        cancelChan <-chan struct{}, timeoutChan chan<- error) {
37✔
UNCOV
3282

×
UNCOV
3283
        defer f.wg.Done()
×
3284

3285
        epochClient, err := f.cfg.Notifier.RegisterBlockEpochNtfn(nil)
3286
        if err != nil {
37✔
3287
                timeoutChan <- fmt.Errorf("unable to register for epoch "+
3288
                        "notification: %v", err)
3289
                return
3290
        }
3291

3292
        defer epochClient.Cancel()
3293

3294
        // The value of waitBlocksForFundingConf is adjusted in a development
3295
        // environment to enhance test capabilities. Otherwise, it is set to
3296
        // DefaultMaxWaitNumBlocksFundingConf.
3297
        waitBlocksForFundingConf := uint32(
29✔
3298
                lncfg.DefaultMaxWaitNumBlocksFundingConf,
29✔
3299
        )
29✔
3300

29✔
3301
        if lncfg.IsDevBuild() {
29✔
3302
                waitBlocksForFundingConf =
29✔
UNCOV
3303
                        f.cfg.Dev.MaxWaitNumBlocksFundingConf
×
UNCOV
3304
        }
×
UNCOV
3305

×
UNCOV
3306
        // On block maxHeight we will cancel the funding confirmation wait.
×
3307
        broadcastHeight := completeChan.BroadcastHeight()
3308
        maxHeight := broadcastHeight + waitBlocksForFundingConf
29✔
3309
        for {
29✔
3310
                select {
29✔
3311
                case epoch, ok := <-epochClient.Epochs:
29✔
3312
                        if !ok {
29✔
3313
                                timeoutChan <- fmt.Errorf("epoch client " +
29✔
3314
                                        "shutting down")
29✔
3315
                                return
29✔
3316
                        }
29✔
3317

32✔
3318
                        // Close the timeout channel and exit if the block is
3✔
3319
                        // above the max height.
3✔
3320
                        if uint32(epoch.Height) >= maxHeight {
3✔
3321
                                log.Warnf("Waited for %v blocks without "+
3322
                                        "seeing funding transaction confirmed,"+
3323
                                        " cancelling.",
29✔
3324
                                        waitBlocksForFundingConf)
29✔
3325

60✔
3326
                                // Notify the caller of the timeout.
31✔
3327
                                close(timeoutChan)
7✔
3328
                                return
7✔
UNCOV
3329
                        }
×
UNCOV
3330

×
UNCOV
3331
                        // TODO: If we are the channel initiator implement
×
UNCOV
3332
                        // a method for recovering the funds from the funding
×
3333
                        // transaction
3334

3335
                case <-cancelChan:
3336
                        return
12✔
3337

5✔
3338
                case <-f.quit:
5✔
3339
                        // The fundingManager is shutting down, will resume
5✔
3340
                        // waiting for the funding transaction on startup.
5✔
3341
                        return
5✔
3342
                }
5✔
3343
        }
5✔
3344
}
5✔
3345

5✔
3346
// makeLabelForTx updates the label for the confirmed funding transaction. If
3347
// we opened the channel, and lnd's wallet published our funding tx (which is
3348
// not the case for some channels) then we update our transaction label with
3349
// our short channel ID, which is known now that our funding transaction has
3350
// confirmed. We do not label transactions we did not publish, because our
3351
// wallet has no knowledge of them.
18✔
3352
func (f *Manager) makeLabelForTx(c *channeldb.OpenChannel) {
18✔
3353
        if c.IsInitiator && c.ChanType.HasFundingTx() {
3354
                shortChanID := c.ShortChanID()
12✔
3355

12✔
3356
                // For zero-conf channels, we'll use the actually-confirmed
12✔
3357
                // short channel id.
12✔
3358
                if c.IsZeroConf() {
3359
                        shortChanID = c.ZeroConfRealScid()
3360
                }
3361

3362
                label := labels.MakeLabel(
3363
                        labels.LabelTypeChannelOpen, &shortChanID,
3364
                )
3365

3366
                err := f.cfg.UpdateLabel(c.FundingOutpoint.Hash, label)
3367
                if err != nil {
3368
                        log.Errorf("unable to update label: %v", err)
37✔
3369
                }
56✔
3370
        }
19✔
3371
}
19✔
3372

19✔
3373
// handleFundingConfirmation marks a channel as open in the database, and set
19✔
3374
// the channelOpeningState markedOpen. In addition it will report the now
24✔
3375
// decided short channel ID to the switch, and close the local discovery signal
5✔
3376
// for this channel.
5✔
3377
func (f *Manager) handleFundingConfirmation(
3378
        completeChan *channeldb.OpenChannel,
19✔
3379
        confChannel *confirmedChannel) error {
19✔
3380

19✔
3381
        fundingPoint := completeChan.FundingOutpoint
19✔
3382
        chanID := lnwire.NewChanIDFromOutPoint(fundingPoint)
19✔
3383

19✔
UNCOV
3384
        // TODO(roasbeef): ideally persistent state update for chan above
×
UNCOV
3385
        // should be abstracted
×
3386

3387
        // Now that that the channel has been fully confirmed, we'll request
3388
        // that the wallet fully verify this channel to ensure that it can be
3389
        // used.
3390
        err := f.cfg.Wallet.ValidateChannel(completeChan, confChannel.fundingTx)
3391
        if err != nil {
3392
                // TODO(roasbeef): delete chan state?
3393
                return fmt.Errorf("unable to validate channel: %w", err)
3394
        }
3395

33✔
3396
        // Now that the channel has been validated, we'll persist an alias for
33✔
3397
        // this channel if the option-scid-alias feature-bit was negotiated.
33✔
3398
        if completeChan.NegotiatedAliasFeature() {
33✔
3399
                aliasScid, err := f.cfg.AliasManager.RequestAlias()
33✔
3400
                if err != nil {
33✔
3401
                        return fmt.Errorf("unable to request alias: %w", err)
33✔
3402
                }
33✔
3403

33✔
3404
                err = f.cfg.AliasManager.AddLocalAlias(
33✔
3405
                        aliasScid, confChannel.shortChanID, true, false,
33✔
3406
                )
33✔
3407
                if err != nil {
33✔
3408
                        return fmt.Errorf("unable to request alias: %w", err)
×
3409
                }
×
UNCOV
3410
        }
×
3411

3412
        // The funding transaction now being confirmed, we add this channel to
3413
        // the fundingManager's internal persistent state machine that we use
3414
        // to track the remaining process of the channel opening. This is
38✔
3415
        // useful to resume the opening process in case of restarts. We set the
5✔
3416
        // opening state before we mark the channel opened in the database,
5✔
UNCOV
3417
        // such that we can receover from one of the db writes failing.
×
UNCOV
3418
        err = f.saveChannelOpeningState(
×
3419
                &fundingPoint, markedOpen, &confChannel.shortChanID,
3420
        )
5✔
3421
        if err != nil {
5✔
3422
                return fmt.Errorf("error setting channel state to "+
5✔
3423
                        "markedOpen: %v", err)
5✔
3424
        }
×
UNCOV
3425

×
3426
        // Now that the channel has been fully confirmed and we successfully
3427
        // saved the opening state, we'll mark it as open within the database.
3428
        err = completeChan.MarkAsOpen(confChannel.shortChanID)
3429
        if err != nil {
3430
                return fmt.Errorf("error setting channel pending flag to "+
3431
                        "false:        %v", err)
3432
        }
3433

3434
        // Update the confirmed funding transaction label.
33✔
3435
        f.makeLabelForTx(completeChan)
33✔
3436

33✔
3437
        // Inform the ChannelNotifier that the channel has transitioned from
33✔
UNCOV
3438
        // pending open to open.
×
UNCOV
3439
        f.cfg.NotifyOpenChannelEvent(
×
UNCOV
3440
                completeChan.FundingOutpoint, completeChan.IdentityPub,
×
3441
        )
3442

3443
        // Close the discoverySignal channel, indicating to a separate
3444
        // goroutine that the channel now is marked as open in the database
33✔
3445
        // and that it is acceptable to process channel_ready messages
33✔
UNCOV
3446
        // from the peer.
×
UNCOV
3447
        if discoverySignal, ok := f.localDiscoverySignals.Load(chanID); ok {
×
UNCOV
3448
                close(discoverySignal)
×
3449
        }
3450

3451
        return nil
33✔
3452
}
33✔
3453

33✔
3454
// sendChannelReady creates and sends the channelReady message.
33✔
3455
// This should be called after the funding transaction has been confirmed,
33✔
3456
// and the channelState is 'markedOpen'.
33✔
3457
func (f *Manager) sendChannelReady(completeChan *channeldb.OpenChannel,
33✔
3458
        channel *lnwallet.LightningChannel) error {
33✔
3459

33✔
3460
        chanID := lnwire.NewChanIDFromOutPoint(completeChan.FundingOutpoint)
33✔
3461

33✔
3462
        var peerKey [33]byte
33✔
3463
        copy(peerKey[:], completeChan.IdentityPub.SerializeCompressed())
66✔
3464

33✔
3465
        // Next, we'll send over the channel_ready message which marks that we
33✔
3466
        // consider the channel open by presenting the remote party with our
3467
        // next revocation key. Without the revocation key, the remote party
33✔
3468
        // will be unable to propose state transitions.
3469
        nextRevocation, err := channel.NextRevocationKey()
3470
        if err != nil {
3471
                return fmt.Errorf("unable to create next revocation: %w", err)
3472
        }
3473
        channelReadyMsg := lnwire.NewChannelReady(chanID, nextRevocation)
3474

38✔
3475
        // If this is a taproot channel, then we also need to send along our
38✔
3476
        // set of musig2 nonces as well.
38✔
3477
        if completeChan.ChanType.IsTaproot() {
38✔
3478
                log.Infof("ChanID(%v): generating musig2 nonces...",
38✔
3479
                        chanID)
38✔
3480

38✔
3481
                f.nonceMtx.Lock()
38✔
3482
                localNonce, ok := f.pendingMusigNonces[chanID]
38✔
3483
                if !ok {
38✔
3484
                        // If we don't have any nonces generated yet for this
38✔
3485
                        // first state, then we'll generate them now and stow
38✔
3486
                        // them away.  When we receive the funding locked
38✔
UNCOV
3487
                        // message, we'll then pass along this same set of
×
UNCOV
3488
                        // nonces.
×
3489
                        newNonce, err := channel.GenMusigNonces()
38✔
3490
                        if err != nil {
38✔
3491
                                f.nonceMtx.Unlock()
38✔
3492
                                return err
38✔
3493
                        }
45✔
3494

7✔
3495
                        // Now that we've generated the nonce for this channel,
7✔
3496
                        // we'll store it in the set of pending nonces.
7✔
3497
                        localNonce = newNonce
7✔
3498
                        f.pendingMusigNonces[chanID] = localNonce
7✔
3499
                }
14✔
3500
                f.nonceMtx.Unlock()
7✔
3501

7✔
3502
                channelReadyMsg.NextLocalNonce = lnwire.SomeMusig2Nonce(
7✔
3503
                        localNonce.PubNonce,
7✔
3504
                )
7✔
3505
        }
7✔
3506

7✔
UNCOV
3507
        // If the channel negotiated the option-scid-alias feature bit, we'll
×
UNCOV
3508
        // send a TLV segment that includes an alias the peer can use in their
×
UNCOV
3509
        // invoice hop hints. We'll send the first alias we find for the
×
3510
        // channel since it does not matter which alias we send. We'll error
3511
        // out in the odd case that no aliases are found.
3512
        if completeChan.NegotiatedAliasFeature() {
3513
                aliases := f.cfg.AliasManager.GetAliases(
7✔
3514
                        completeChan.ShortChanID(),
7✔
3515
                )
3516
                if len(aliases) == 0 {
7✔
3517
                        return fmt.Errorf("no aliases found")
7✔
3518
                }
7✔
3519

7✔
3520
                // We can use a pointer to aliases since GetAliases returns a
7✔
3521
                // copy of the alias slice.
3522
                channelReadyMsg.AliasScid = &aliases[0]
3523
        }
3524

3525
        // If the peer has disconnected before we reach this point, we will need
3526
        // to wait for him to come back online before sending the channelReady
3527
        // message. This is special for channelReady, since failing to send any
3528
        // of the previous messages in the funding flow just cancels the flow.
47✔
3529
        // But now the funding transaction is confirmed, the channel is open
9✔
3530
        // and we have to make sure the peer gets the channelReady message when
9✔
3531
        // it comes back online. This is also crucial during restart of lnd,
9✔
3532
        // where we might try to resend the channelReady message before the
9✔
UNCOV
3533
        // server has had the time to connect to the peer. We keep trying to
×
UNCOV
3534
        // send channelReady until we succeed, or the fundingManager is shut
×
3535
        // down.
3536
        for {
3537
                peer, err := f.waitForPeerOnline(completeChan.IdentityPub)
3538
                if err != nil {
9✔
3539
                        return err
3540
                }
3541

3542
                localAlias := peer.LocalFeatures().HasFeature(
3543
                        lnwire.ScidAliasOptional,
3544
                )
3545
                remoteAlias := peer.RemoteFeatures().HasFeature(
3546
                        lnwire.ScidAliasOptional,
3547
                )
3548

3549
                // We could also refresh the channel state instead of checking
3550
                // whether the feature was negotiated, but this saves us a
3551
                // database read.
3552
                if channelReadyMsg.AliasScid == nil && localAlias &&
76✔
3553
                        remoteAlias {
38✔
3554

39✔
3555
                        // If an alias was not assigned above and the scid
1✔
3556
                        // alias feature was negotiated, check if we already
1✔
3557
                        // have an alias stored in case handleChannelReady was
3558
                        // called before this. If an alias exists, use that in
37✔
3559
                        // channel_ready. Otherwise, request and store an
37✔
3560
                        // alias and use that.
37✔
3561
                        aliases := f.cfg.AliasManager.GetAliases(
37✔
3562
                                completeChan.ShortChannelID,
37✔
3563
                        )
37✔
3564
                        if len(aliases) == 0 {
37✔
3565
                                // No aliases were found.
37✔
3566
                                alias, err := f.cfg.AliasManager.RequestAlias()
37✔
3567
                                if err != nil {
37✔
3568
                                        return err
37✔
3569
                                }
37✔
UNCOV
3570

×
3571
                                err = f.cfg.AliasManager.AddLocalAlias(
×
3572
                                        alias, completeChan.ShortChannelID,
×
3573
                                        false, false,
×
3574
                                )
×
3575
                                if err != nil {
×
3576
                                        return err
×
3577
                                }
×
UNCOV
3578

×
3579
                                channelReadyMsg.AliasScid = &alias
×
3580
                        } else {
×
3581
                                channelReadyMsg.AliasScid = &aliases[0]
×
3582
                        }
×
UNCOV
3583
                }
×
UNCOV
3584

×
UNCOV
3585
                log.Infof("Peer(%x) is online, sending ChannelReady "+
×
3586
                        "for ChannelID(%v)", peerKey, chanID)
UNCOV
3587

×
UNCOV
3588
                if err := peer.SendMessage(true, channelReadyMsg); err == nil {
×
UNCOV
3589
                        // Sending succeeded, we can break out and continue the
×
UNCOV
3590
                        // funding flow.
×
UNCOV
3591
                        break
×
UNCOV
3592
                }
×
UNCOV
3593

×
3594
                log.Warnf("Unable to send channelReady to peer %x: %v. "+
3595
                        "Will retry when online", peerKey, err)
×
UNCOV
3596
        }
×
UNCOV
3597

×
UNCOV
3598
        return nil
×
3599
}
3600

3601
// receivedChannelReady checks whether or not we've received a ChannelReady
37✔
3602
// from the remote peer. If we have, RemoteNextRevocation will be set.
37✔
3603
func (f *Manager) receivedChannelReady(node *btcec.PublicKey,
37✔
3604
        chanID lnwire.ChannelID) (bool, error) {
74✔
3605

37✔
3606
        // If the funding manager has exited, return an error to stop looping.
37✔
3607
        // Note that the peer may appear as online while the funding manager
37✔
3608
        // has stopped due to the shutdown order in the server.
3609
        select {
3610
        case <-f.quit:
×
3611
                return false, ErrFundingManagerShuttingDown
×
3612
        default:
3613
        }
3614

37✔
3615
        // Avoid a tight loop if peer is offline.
3616
        if _, err := f.waitForPeerOnline(node); err != nil {
3617
                log.Errorf("Wait for peer online failed: %v", err)
3618
                return false, err
3619
        }
3620

63✔
3621
        // If we cannot find the channel, then we haven't processed the
63✔
3622
        // remote's channelReady message.
63✔
3623
        channel, err := f.cfg.FindChannel(node, chanID)
63✔
3624
        if err != nil {
63✔
3625
                log.Errorf("Unable to locate ChannelID(%v) to determine if "+
63✔
3626
                        "ChannelReady was received", chanID)
1✔
3627
                return false, err
1✔
3628
        }
62✔
3629

3630
        // If we haven't insert the next revocation point, we haven't finished
3631
        // processing the channel ready message.
3632
        if channel.RemoteNextRevocation == nil {
62✔
UNCOV
3633
                return false, nil
×
UNCOV
3634
        }
×
UNCOV
3635

×
3636
        // Finally, the barrier signal is removed once we finish
3637
        // `handleChannelReady`. If we can still find the signal, we haven't
3638
        // finished processing it yet.
3639
        _, loaded := f.handleChannelReadyBarriers.Load(chanID)
62✔
3640

62✔
UNCOV
3641
        return !loaded, nil
×
UNCOV
3642
}
×
UNCOV
3643

×
UNCOV
3644
// extractAnnounceParams extracts the various channel announcement and update
×
3645
// parameters that will be needed to construct a ChannelAnnouncement and a
3646
// ChannelUpdate.
3647
func (f *Manager) extractAnnounceParams(c *channeldb.OpenChannel) (
3648
        lnwire.MilliSatoshi, lnwire.MilliSatoshi) {
100✔
3649

38✔
3650
        // We'll obtain the min HTLC value we can forward in our direction, as
38✔
3651
        // we'll use this value within our ChannelUpdate. This constraint is
3652
        // originally set by the remote node, as it will be the one that will
3653
        // need to determine the smallest HTLC it deems economically relevant.
3654
        fwdMinHTLC := c.LocalChanCfg.MinHTLC
3655

27✔
3656
        // We don't necessarily want to go as low as the remote party allows.
27✔
3657
        // Check it against our default forwarding policy.
27✔
3658
        if fwdMinHTLC < f.cfg.DefaultRoutingPolicy.MinHTLCOut {
3659
                fwdMinHTLC = f.cfg.DefaultRoutingPolicy.MinHTLCOut
3660
        }
3661

3662
        // We'll obtain the max HTLC value we can forward in our direction, as
3663
        // we'll use this value within our ChannelUpdate. This value must be <=
3664
        // channel capacity and <= the maximum in-flight msats set by the peer.
29✔
3665
        fwdMaxHTLC := c.LocalChanCfg.MaxPendingAmount
29✔
3666
        capacityMSat := lnwire.NewMSatFromSatoshis(c.Capacity)
29✔
3667
        if fwdMaxHTLC > capacityMSat {
29✔
3668
                fwdMaxHTLC = capacityMSat
29✔
3669
        }
29✔
3670

29✔
3671
        return fwdMinHTLC, fwdMaxHTLC
29✔
3672
}
29✔
3673

29✔
3674
// addToGraph sends a ChannelAnnouncement and a ChannelUpdate to the
32✔
3675
// gossiper so that the channel is added to the graph builder's internal graph.
3✔
3676
// These announcement messages are NOT broadcasted to the greater network,
3✔
3677
// only to the channel counter party. The proofs required to announce the
3678
// channel to the greater network will be created and sent in annAfterSixConfs.
3679
// The peerAlias is used for zero-conf channels to give the counter-party a
3680
// ChannelUpdate they understand. ourPolicy may be set for various
3681
// option-scid-alias channels to re-use the same policy.
29✔
3682
func (f *Manager) addToGraph(completeChan *channeldb.OpenChannel,
29✔
3683
        shortChanID *lnwire.ShortChannelID,
29✔
UNCOV
3684
        peerAlias *lnwire.ShortChannelID,
×
UNCOV
3685
        ourPolicy *models.ChannelEdgePolicy) error {
×
3686

3687
        chanID := lnwire.NewChanIDFromOutPoint(completeChan.FundingOutpoint)
29✔
3688

3689
        fwdMinHTLC, fwdMaxHTLC := f.extractAnnounceParams(completeChan)
3690

3691
        ann, err := f.newChanAnnouncement(
3692
                f.cfg.IDKey, completeChan.IdentityPub,
3693
                &completeChan.LocalChanCfg.MultiSigKey,
3694
                completeChan.RemoteChanCfg.MultiSigKey.PubKey, *shortChanID,
3695
                chanID, fwdMinHTLC, fwdMaxHTLC, ourPolicy,
3696
                completeChan.ChanType,
3697
        )
3698
        if err != nil {
3699
                return fmt.Errorf("error generating channel "+
3700
                        "announcement: %v", err)
3701
        }
29✔
3702

29✔
3703
        // Send ChannelAnnouncement and ChannelUpdate to the gossiper to add
29✔
3704
        // to the Router's topology.
29✔
3705
        errChan := f.cfg.SendAnnouncement(
29✔
3706
                ann.chanAnn, discovery.ChannelCapacity(completeChan.Capacity),
29✔
3707
                discovery.ChannelPoint(completeChan.FundingOutpoint),
29✔
3708
                discovery.TapscriptRoot(completeChan.TapscriptRoot),
29✔
3709
        )
29✔
3710
        select {
29✔
3711
        case err := <-errChan:
29✔
3712
                if err != nil {
29✔
3713
                        if graph.IsError(err, graph.ErrOutdated,
29✔
3714
                                graph.ErrIgnored) {
29✔
3715

×
3716
                                log.Debugf("Graph rejected "+
×
3717
                                        "ChannelAnnouncement: %v", err)
×
3718
                        } else {
3719
                                return fmt.Errorf("error sending channel "+
3720
                                        "announcement: %v", err)
3721
                        }
29✔
3722
                }
29✔
3723
        case <-f.quit:
29✔
3724
                return ErrFundingManagerShuttingDown
29✔
3725
        }
29✔
3726

29✔
3727
        errChan = f.cfg.SendAnnouncement(
29✔
3728
                ann.chanUpdateAnn, discovery.RemoteAlias(peerAlias),
29✔
UNCOV
3729
        )
×
UNCOV
3730
        select {
×
UNCOV
3731
        case err := <-errChan:
×
UNCOV
3732
                if err != nil {
×
3733
                        if graph.IsError(err, graph.ErrOutdated,
×
3734
                                graph.ErrIgnored) {
×
3735

×
3736
                                log.Debugf("Graph rejected "+
×
3737
                                        "ChannelUpdate: %v", err)
×
3738
                        } else {
3739
                                return fmt.Errorf("error sending channel "+
×
3740
                                        "update: %v", err)
×
3741
                        }
3742
                }
3743
        case <-f.quit:
29✔
3744
                return ErrFundingManagerShuttingDown
29✔
3745
        }
29✔
3746

29✔
3747
        return nil
29✔
3748
}
29✔
UNCOV
3749

×
UNCOV
3750
// annAfterSixConfs broadcasts the necessary channel announcement messages to
×
UNCOV
3751
// the network after 6 confs. Should be called after the channelReady message
×
UNCOV
3752
// is sent and the channel is added to the graph (channelState is
×
UNCOV
3753
// 'addedToGraph') and the channel is ready to be used. This is the last
×
UNCOV
3754
// step in the channel opening process, and the opening state will be deleted
×
UNCOV
3755
// from the database if successful.
×
UNCOV
3756
func (f *Manager) annAfterSixConfs(completeChan *channeldb.OpenChannel,
×
UNCOV
3757
        shortChanID *lnwire.ShortChannelID) error {
×
3758

UNCOV
3759
        // If this channel is not meant to be announced to the greater network,
×
UNCOV
3760
        // we'll only send our NodeAnnouncement1 to our counterparty to ensure
×
3761
        // we don't leak any of our information.
3762
        announceChan := completeChan.ChannelFlags&lnwire.FFAnnounceChannel != 0
3763
        if !announceChan {
29✔
3764
                log.Debugf("Will not announce private channel %v.",
3765
                        shortChanID.ToUint64())
3766

3767
                peer, err := f.waitForPeerOnline(completeChan.IdentityPub)
3768
                if err != nil {
3769
                        return err
3770
                }
3771

3772
                nodeAnn, err := f.cfg.CurrentNodeAnnouncement()
3773
                if err != nil {
29✔
3774
                        return fmt.Errorf("unable to retrieve current node "+
29✔
3775
                                "announcement: %v", err)
29✔
3776
                }
29✔
3777

29✔
3778
                chanID := lnwire.NewChanIDFromOutPoint(
29✔
3779
                        completeChan.FundingOutpoint,
40✔
3780
                )
11✔
3781
                pubKey := peer.PubKey()
11✔
3782
                log.Debugf("Sending our NodeAnnouncement1 for "+
11✔
3783
                        "ChannelID(%v) to %x", chanID, pubKey)
11✔
3784

11✔
UNCOV
3785
                // TODO(halseth): make reliable. If the peer is not online this
×
UNCOV
3786
                // will fail, and the opening process will stop. Should instead
×
3787
                // block here, waiting for the peer to come online.
3788
                if err := peer.SendMessage(true, &nodeAnn); err != nil {
11✔
3789
                        return fmt.Errorf("unable to send node announcement "+
11✔
3790
                                "to peer %x: %v", pubKey, err)
×
3791
                }
×
UNCOV
3792
        } else {
×
3793
                // Otherwise, we'll wait until the funding transaction has
3794
                // reached 6 confirmations before announcing it.
11✔
3795
                numConfs := uint32(completeChan.NumConfsRequired)
11✔
3796
                if numConfs < 6 {
11✔
3797
                        numConfs = 6
11✔
3798
                }
11✔
3799
                txid := completeChan.FundingOutpoint.Hash
11✔
3800
                log.Debugf("Will announce channel %v after ChannelPoint"+
11✔
3801
                        "(%v) has gotten %d confirmations",
11✔
3802
                        shortChanID.ToUint64(), completeChan.FundingOutpoint,
11✔
3803
                        numConfs)
11✔
3804

11✔
UNCOV
3805
                fundingScript, err := makeFundingScript(completeChan)
×
UNCOV
3806
                if err != nil {
×
3807
                        return fmt.Errorf("unable to create funding script "+
×
3808
                                "for ChannelPoint(%v): %v",
21✔
3809
                                completeChan.FundingOutpoint, err)
21✔
3810
                }
21✔
3811

21✔
3812
                // Register with the ChainNotifier for a notification once the
42✔
3813
                // funding transaction reaches at least 6 confirmations.
21✔
3814
                confNtfn, err := f.cfg.Notifier.RegisterConfirmationsNtfn(
21✔
3815
                        &txid, fundingScript, numConfs,
21✔
3816
                        completeChan.BroadcastHeight(),
21✔
3817
                )
21✔
3818
                if err != nil {
21✔
3819
                        return fmt.Errorf("unable to register for "+
21✔
3820
                                "confirmation of ChannelPoint(%v): %v",
21✔
3821
                                completeChan.FundingOutpoint, err)
21✔
3822
                }
21✔
UNCOV
3823

×
UNCOV
3824
                // Wait until 6 confirmations has been reached or the wallet
×
UNCOV
3825
                // signals a shutdown.
×
UNCOV
3826
                select {
×
3827
                case _, ok := <-confNtfn.Confirmed:
3828
                        if !ok {
3829
                                return fmt.Errorf("ChainNotifier shutting "+
3830
                                        "down, cannot complete funding flow "+
21✔
3831
                                        "for ChannelPoint(%v)",
21✔
3832
                                        completeChan.FundingOutpoint)
21✔
3833
                        }
21✔
3834
                        // Fallthrough.
21✔
UNCOV
3835

×
UNCOV
3836
                case <-f.quit:
×
UNCOV
3837
                        return fmt.Errorf("%v, stopping funding flow for "+
×
UNCOV
3838
                                "ChannelPoint(%v)",
×
3839
                                ErrFundingManagerShuttingDown,
3840
                                completeChan.FundingOutpoint)
3841
                }
3842

21✔
3843
                fundingPoint := completeChan.FundingOutpoint
19✔
3844
                chanID := lnwire.NewChanIDFromOutPoint(fundingPoint)
19✔
UNCOV
3845

×
UNCOV
3846
                log.Infof("Announcing ChannelPoint(%v), short_chan_id=%v",
×
UNCOV
3847
                        &fundingPoint, shortChanID)
×
UNCOV
3848

×
UNCOV
3849
                // If this is a non-zero-conf option-scid-alias channel, we'll
×
3850
                // delete the mappings the gossiper uses so that ChannelUpdates
3851
                // with aliases won't be accepted. This is done elsewhere for
3852
                // zero-conf channels.
5✔
3853
                isScidFeature := completeChan.NegotiatedAliasFeature()
5✔
3854
                isZeroConf := completeChan.IsZeroConf()
5✔
3855
                if isScidFeature && !isZeroConf {
5✔
3856
                        baseScid := completeChan.ShortChanID()
5✔
3857
                        err := f.cfg.AliasManager.DeleteSixConfs(baseScid)
3858
                        if err != nil {
3859
                                return fmt.Errorf("failed deleting six confs "+
19✔
3860
                                        "maps: %v", err)
19✔
3861
                        }
19✔
3862

19✔
3863
                        // We'll delete the edge and add it again via
19✔
3864
                        // addToGraph. This is because the peer may have
19✔
3865
                        // sent us a ChannelUpdate with an alias and we don't
19✔
3866
                        // want to relay this.
19✔
3867
                        ourPolicy, err := f.cfg.DeleteAliasEdge(baseScid)
19✔
3868
                        if err != nil {
19✔
3869
                                return fmt.Errorf("failed deleting real edge "+
19✔
3870
                                        "for alias channel from graph: %v",
19✔
3871
                                        err)
22✔
3872
                        }
3✔
3873

3✔
3874
                        err = f.addToGraph(
3✔
UNCOV
3875
                                completeChan, &baseScid, nil, ourPolicy,
×
UNCOV
3876
                        )
×
UNCOV
3877
                        if err != nil {
×
3878
                                return fmt.Errorf("failed to re-add to "+
3879
                                        "graph: %v", err)
3880
                        }
3881
                }
3882

3883
                // Create and broadcast the proofs required to make this channel
3✔
3884
                // public and usable for other nodes for routing.
3✔
UNCOV
3885
                err = f.announceChannel(
×
UNCOV
3886
                        f.cfg.IDKey, completeChan.IdentityPub,
×
UNCOV
3887
                        &completeChan.LocalChanCfg.MultiSigKey,
×
UNCOV
3888
                        completeChan.RemoteChanCfg.MultiSigKey.PubKey,
×
3889
                        *shortChanID, chanID, completeChan.ChanType,
3890
                )
3✔
3891
                if err != nil {
3✔
3892
                        return fmt.Errorf("channel announcement failed: %w",
3✔
3893
                                err)
3✔
UNCOV
3894
                }
×
UNCOV
3895

×
UNCOV
3896
                log.Debugf("Channel with ChannelPoint(%v), short_chan_id=%v "+
×
3897
                        "sent to gossiper", &fundingPoint, shortChanID)
3898
        }
3899

3900
        return nil
3901
}
19✔
3902

19✔
3903
// waitForZeroConfChannel is called when the state is addedToGraph with
19✔
3904
// a zero-conf channel. This will wait for the real confirmation, add the
19✔
3905
// confirmed SCID to the router graph, and then announce after six confs.
19✔
3906
func (f *Manager) waitForZeroConfChannel(c *channeldb.OpenChannel) error {
19✔
3907
        // First we'll check whether the channel is confirmed on-chain. If it
22✔
3908
        // is already confirmed, the chainntnfs subsystem will return with the
3✔
3909
        // confirmed tx. Otherwise, we'll wait here until confirmation occurs.
3✔
3910
        confChan, err := f.waitForFundingWithTimeout(c)
3✔
3911
        if err != nil {
3912
                return fmt.Errorf("error waiting for zero-conf funding "+
19✔
3913
                        "confirmation for ChannelPoint(%v): %v",
19✔
3914
                        c.FundingOutpoint, err)
3915
        }
3916

27✔
3917
        // We'll need to refresh the channel state so that things are properly
3918
        // populated when validating the channel state. Otherwise, a panic may
3919
        // occur due to inconsistency in the OpenChannel struct.
3920
        err = c.Refresh()
3921
        if err != nil {
3922
                return fmt.Errorf("unable to refresh channel state: %w", err)
9✔
3923
        }
9✔
3924

9✔
3925
        // Now that we have the confirmed transaction and the proper SCID,
9✔
3926
        // we'll call ValidateChannel to ensure the confirmed tx is properly
9✔
3927
        // formatted.
14✔
3928
        err = f.cfg.Wallet.ValidateChannel(c, confChan.fundingTx)
5✔
3929
        if err != nil {
5✔
3930
                return fmt.Errorf("unable to validate zero-conf channel: "+
5✔
3931
                        "%v", err)
5✔
3932
        }
3933

3934
        // Once we know the confirmed ShortChannelID, we'll need to save it to
3935
        // the database and refresh the OpenChannel struct with it.
3936
        err = c.MarkRealScid(confChan.shortChanID)
7✔
3937
        if err != nil {
10✔
3938
                return fmt.Errorf("unable to set confirmed SCID for zero "+
3✔
3939
                        "channel: %v", err)
3✔
3940
        }
3941

3942
        // Six confirmations have been reached. If this channel is public,
3943
        // we'll delete some of the alias mappings the gossiper uses.
3944
        isPublic := c.ChannelFlags&lnwire.FFAnnounceChannel != 0
7✔
3945
        if isPublic {
7✔
UNCOV
3946
                err = f.cfg.AliasManager.DeleteSixConfs(c.ShortChannelID)
×
UNCOV
3947
                if err != nil {
×
3948
                        return fmt.Errorf("unable to delete base alias after "+
×
3949
                                "six confirmations: %v", err)
3950
                }
3951

3952
                // TODO: Make this atomic!
7✔
3953
                ourPolicy, err := f.cfg.DeleteAliasEdge(c.ShortChanID())
7✔
UNCOV
3954
                if err != nil {
×
3955
                        return fmt.Errorf("unable to delete alias edge from "+
×
3956
                                "graph: %v", err)
×
3957
                }
3958

3959
                // We'll need to update the graph with the new ShortChannelID
3960
                // via an addToGraph call. We don't pass in the peer's
7✔
3961
                // alias since we'll be using the confirmed SCID from now on
12✔
3962
                // regardless if it's public or not.
5✔
3963
                err = f.addToGraph(
5✔
UNCOV
3964
                        c, &confChan.shortChanID, nil, ourPolicy,
×
UNCOV
3965
                )
×
UNCOV
3966
                if err != nil {
×
3967
                        return fmt.Errorf("failed adding confirmed zero-conf "+
3968
                                "SCID to graph: %v", err)
3969
                }
5✔
3970
        }
5✔
UNCOV
3971

×
UNCOV
3972
        // Since we have now marked down the confirmed SCID, we'll also need to
×
UNCOV
3973
        // tell the Switch to refresh the relevant ChannelLink so that forwards
×
3974
        // under the confirmed SCID are possible if this is a public channel.
3975
        err = f.cfg.ReportShortChanID(c.FundingOutpoint)
3976
        if err != nil {
3977
                // This should only fail if the link is not found in the
3978
                // Switch's linkIndex map. If this is the case, then the peer
3979
                // has gone offline and the next time the link is loaded, it
5✔
3980
                // will have a refreshed state. Just log an error here.
5✔
3981
                log.Errorf("unable to report scid for zero-conf channel "+
5✔
3982
                        "channel: %v", err)
5✔
3983
        }
×
UNCOV
3984

×
UNCOV
3985
        // Update the confirmed transaction's label.
×
3986
        f.makeLabelForTx(c)
3987

3988
        return nil
3989
}
3990

3991
// genFirstStateMusigNonce generates a nonces for the "first" local state. This
7✔
3992
// is the verification nonce for the state created for us after the initial
7✔
UNCOV
3993
// commitment transaction signed as part of the funding flow.
×
UNCOV
3994
func genFirstStateMusigNonce(channel *channeldb.OpenChannel,
×
UNCOV
3995
) (*musig2.Nonces, error) {
×
UNCOV
3996

×
UNCOV
3997
        musig2ShaChain, err := channeldb.DeriveMusig2Shachain(
×
UNCOV
3998
                channel.RevocationProducer,
×
UNCOV
3999
        )
×
4000
        if err != nil {
4001
                return nil, fmt.Errorf("unable to generate musig channel "+
4002
                        "nonces: %v", err)
7✔
4003
        }
7✔
4004

7✔
4005
        // We use the _next_ commitment height here as we need to generate the
4006
        // nonce for the next state the remote party will sign for us.
4007
        verNonce, err := channeldb.NewMusigVerificationNonce(
4008
                channel.LocalChanCfg.MultiSigKey.PubKey,
4009
                channel.LocalCommitment.CommitHeight+1,
4010
                musig2ShaChain,
4011
        )
7✔
4012
        if err != nil {
7✔
4013
                return nil, fmt.Errorf("unable to generate musig channel "+
7✔
4014
                        "nonces: %v", err)
7✔
4015
        }
7✔
4016

7✔
UNCOV
4017
        return verNonce, nil
×
UNCOV
4018
}
×
UNCOV
4019

×
4020
// handleChannelReady finalizes the channel funding process and enables the
4021
// channel to enter normal operating mode.
4022
func (f *Manager) handleChannelReady(peer lnpeer.Peer, //nolint:funlen
4023
        msg *lnwire.ChannelReady) {
7✔
4024

7✔
4025
        defer f.wg.Done()
7✔
4026

7✔
4027
        // Notify the aux hook that the specified peer just established a
7✔
4028
        // channel with us, identified by the given channel ID.
7✔
UNCOV
4029
        f.cfg.AuxChannelNegotiator.WhenSome(
×
UNCOV
4030
                func(acn lnwallet.AuxChannelNegotiator) {
×
4031
                        acn.ProcessChannelReady(msg.ChanID, peer.PubKey())
×
4032
                },
4033
        )
7✔
4034

4035
        // If we are in development mode, we'll wait for specified duration
4036
        // before processing the channel ready message.
4037
        if f.cfg.Dev != nil {
4038
                duration := f.cfg.Dev.ProcessChannelReadyWait
4039
                log.Warnf("Channel(%v): sleeping %v before processing "+
31✔
4040
                        "channel_ready", msg.ChanID, duration)
31✔
4041

31✔
4042
                select {
31✔
4043
                case <-time.After(duration):
31✔
4044
                        log.Warnf("Channel(%v): slept %v before processing "+
31✔
4045
                                "channel_ready", msg.ChanID, duration)
31✔
4046
                case <-f.quit:
31✔
4047
                        log.Warnf("Channel(%v): quit sleeping", msg.ChanID)
×
4048
                        return
×
4049
                }
4050
        }
4051

4052
        log.Debugf("Received ChannelReady for ChannelID(%v) from "+
4053
                "peer %x", msg.ChanID,
34✔
4054
                peer.IdentityKey().SerializeCompressed())
3✔
4055

3✔
4056
        // We now load or create a new channel barrier for this channel.
3✔
4057
        _, loaded := f.handleChannelReadyBarriers.LoadOrStore(
3✔
4058
                msg.ChanID, struct{}{},
3✔
4059
        )
3✔
4060

3✔
4061
        // If we are currently in the process of handling a channel_ready
3✔
UNCOV
4062
        // message for this channel, ignore.
×
UNCOV
4063
        if loaded {
×
UNCOV
4064
                log.Infof("Already handling channelReady for "+
×
4065
                        "ChannelID(%v), ignoring.", msg.ChanID)
4066
                return
4067
        }
4068

31✔
4069
        // If not already handling channelReady for this channel, then the
31✔
4070
        // `LoadOrStore` has set up a barrier, and it will be removed once this
31✔
4071
        // function exits.
31✔
4072
        defer f.handleChannelReadyBarriers.Delete(msg.ChanID)
31✔
4073

31✔
4074
        localDiscoverySignal, ok := f.localDiscoverySignals.Load(msg.ChanID)
31✔
4075
        if ok {
31✔
4076
                // Before we proceed with processing the channel_ready
31✔
4077
                // message, we'll wait for the local waitForFundingConfirmation
31✔
4078
                // goroutine to signal that it has the necessary state in
31✔
4079
                // place. Otherwise, we may be missing critical information
35✔
4080
                // required to handle forwarded HTLC's.
4✔
4081
                select {
4✔
4082
                case <-localDiscoverySignal:
4✔
4083
                        // Fallthrough
4✔
4084
                case <-f.quit:
4085
                        return
4086
                }
4087

4088
                // With the signal received, we can now safely delete the entry
30✔
4089
                // from the map.
30✔
4090
                f.localDiscoverySignals.Delete(msg.ChanID)
30✔
4091
        }
58✔
4092

28✔
4093
        // First, we'll attempt to locate the channel whose funding workflow is
28✔
4094
        // being finalized by this message. We go to the database rather than
28✔
4095
        // our reservation map as we may have restarted, mid funding flow. Also
28✔
4096
        // provide the node's public key to make the search faster.
28✔
4097
        chanID := msg.ChanID
28✔
4098
        channel, err := f.cfg.FindChannel(peer.IdentityKey(), chanID)
28✔
4099
        if err != nil {
4100
                log.Errorf("Unable to locate ChannelID(%v), cannot complete "+
3✔
4101
                        "funding", chanID)
3✔
4102
                return
4103
        }
4104

4105
        // If this is a taproot channel, then we can generate the set of nonces
4106
        // the remote party needs to send the next remote commitment here.
28✔
4107
        var firstVerNonce *musig2.Nonces
4108
        if channel.ChanType.IsTaproot() {
4109
                firstVerNonce, err = genFirstStateMusigNonce(channel)
4110
                if err != nil {
4111
                        log.Error(err)
4112
                        return
4113
                }
30✔
4114
        }
30✔
4115

30✔
UNCOV
4116
        // We'll need to store the received TLV alias if the option_scid_alias
×
UNCOV
4117
        // feature was negotiated. This will be used to provide route hints
×
UNCOV
4118
        // during invoice creation. In the zero-conf case, it is also used to
×
UNCOV
4119
        // provide a ChannelUpdate to the remote peer. This is done before the
×
4120
        // call to InsertNextRevocation in case the call to PutPeerAlias fails.
4121
        // If it were to fail on the first call to handleChannelReady, we
4122
        // wouldn't want the channel to be usable yet.
4123
        if channel.NegotiatedAliasFeature() {
30✔
4124
                // If the AliasScid field is nil, we must fail out. We will
37✔
4125
                // most likely not be able to route through the peer.
7✔
4126
                if msg.AliasScid == nil {
7✔
4127
                        log.Debugf("Consider closing ChannelID(%v), peer "+
×
4128
                                "does not implement the option-scid-alias "+
×
4129
                                "feature properly", chanID)
×
4130
                        return
4131
                }
4132

4133
                // We'll store the AliasScid so that invoice creation can use
4134
                // it.
4135
                err = f.cfg.AliasManager.PutPeerAlias(chanID, *msg.AliasScid)
4136
                if err != nil {
4137
                        log.Errorf("unable to store peer's alias: %v", err)
4138
                        return
4139
                }
39✔
4140

9✔
4141
                // If we do not have an alias stored, we'll create one now.
9✔
4142
                // This is only used in the upgrade case where a user toggles
9✔
UNCOV
4143
                // the option-scid-alias feature-bit to on. We'll also send the
×
UNCOV
4144
                // channel_ready message here in case the link is created
×
UNCOV
4145
                // before sendChannelReady is called.
×
UNCOV
4146
                aliases := f.cfg.AliasManager.GetAliases(
×
UNCOV
4147
                        channel.ShortChannelID,
×
4148
                )
4149
                if len(aliases) == 0 {
4150
                        // No aliases were found so we'll request and store an
4151
                        // alias and use it in the channel_ready message.
9✔
4152
                        alias, err := f.cfg.AliasManager.RequestAlias()
9✔
4153
                        if err != nil {
×
4154
                                log.Errorf("unable to request alias: %v", err)
×
4155
                                return
×
4156
                        }
4157

4158
                        err = f.cfg.AliasManager.AddLocalAlias(
4159
                                alias, channel.ShortChannelID, false, false,
4160
                        )
4161
                        if err != nil {
4162
                                log.Errorf("unable to add local alias: %v",
9✔
4163
                                        err)
9✔
4164
                                return
9✔
4165
                        }
9✔
UNCOV
4166

×
4167
                        secondPoint, err := channel.SecondCommitmentPoint()
×
4168
                        if err != nil {
×
4169
                                log.Errorf("unable to fetch second "+
×
4170
                                        "commitment point: %v", err)
×
4171
                                return
×
4172
                        }
×
4173

4174
                        channelReadyMsg := lnwire.NewChannelReady(
×
4175
                                chanID, secondPoint,
×
4176
                        )
×
4177
                        channelReadyMsg.AliasScid = &alias
×
4178

×
4179
                        if firstVerNonce != nil {
×
4180
                                channelReadyMsg.NextLocalNonce = lnwire.SomeMusig2Nonce( //nolint:ll
×
4181
                                        firstVerNonce.PubNonce,
×
4182
                                )
4183
                        }
×
UNCOV
4184

×
4185
                        err = peer.SendMessage(true, channelReadyMsg)
×
4186
                        if err != nil {
×
4187
                                log.Errorf("unable to send channel_ready: %v",
×
4188
                                        err)
×
4189
                                return
4190
                        }
×
UNCOV
4191
                }
×
UNCOV
4192
        }
×
UNCOV
4193

×
UNCOV
4194
        // If the RemoteNextRevocation is non-nil, it means that we have
×
UNCOV
4195
        // already processed channelReady for this channel, so ignore. This
×
UNCOV
4196
        // check is after the alias logic so we store the peer's most recent
×
UNCOV
4197
        // alias. The spec requires us to validate that subsequent
×
UNCOV
4198
        // channel_ready messages use the same per commitment point (the
×
UNCOV
4199
        // second), but it is not actually necessary since we'll just end up
×
4200
        // ignoring it. We are, however, required to *send* the same per
UNCOV
4201
        // commitment point, since another pedantic implementation might
×
UNCOV
4202
        // verify it.
×
UNCOV
4203
        if channel.RemoteNextRevocation != nil {
×
UNCOV
4204
                log.Infof("Received duplicate channelReady for "+
×
UNCOV
4205
                        "ChannelID(%v), ignoring.", chanID)
×
UNCOV
4206
                return
×
4207
        }
4208

4209
        // If this is a taproot channel, then we'll need to map the received
4210
        // nonces to a nonce pair, and also fetch our pending nonces, which are
4211
        // required in order to make the channel whole.
4212
        var chanOpts []lnwallet.ChannelOpt
4213
        if channel.ChanType.IsTaproot() {
4214
                f.nonceMtx.Lock()
4215
                localNonce, ok := f.pendingMusigNonces[chanID]
4216
                if !ok {
4217
                        // If there's no pending nonce for this channel ID,
4218
                        // we'll use the one generated above.
4219
                        localNonce = firstVerNonce
34✔
4220
                        f.pendingMusigNonces[chanID] = firstVerNonce
4✔
4221
                }
4✔
4222
                f.nonceMtx.Unlock()
4✔
4223

4✔
4224
                log.Infof("ChanID(%v): applying local+remote musig2 nonces",
4225
                        chanID)
4226

4227
                remoteNonce, err := msg.NextLocalNonce.UnwrapOrErrV(
4228
                        errNoLocalNonce,
29✔
4229
                )
36✔
4230
                if err != nil {
7✔
4231
                        cid := newChanIdentifier(msg.ChanID)
7✔
4232
                        f.sendWarning(peer, cid, err)
10✔
4233

3✔
4234
                        return
3✔
4235
                }
3✔
4236

3✔
4237
                chanOpts = append(
3✔
4238
                        chanOpts,
7✔
4239
                        lnwallet.WithLocalMusigNonces(localNonce),
7✔
4240
                        lnwallet.WithRemoteMusigNonces(&musig2.Nonces{
7✔
4241
                                PubNonce: remoteNonce,
7✔
4242
                        }),
7✔
4243
                )
7✔
4244

7✔
4245
                // Inform the aux funding controller that the liquidity in the
7✔
4246
                // custom channel is now ready to be advertised. We potentially
7✔
UNCOV
4247
                // haven't sent our own channel ready message yet, but other
×
UNCOV
4248
                // than that the channel is ready to count toward available
×
UNCOV
4249
                // liquidity.
×
UNCOV
4250
                err = fn.MapOptionZ(
×
UNCOV
4251
                        f.cfg.AuxFundingController,
×
4252
                        func(controller AuxFundingController) error {
4253
                                return controller.ChannelReady(
7✔
4254
                                        lnwallet.NewAuxChanState(channel),
7✔
4255
                                )
7✔
4256
                        },
7✔
4257
                )
7✔
4258
                if err != nil {
7✔
4259
                        cid := newChanIdentifier(msg.ChanID)
7✔
4260
                        f.sendWarning(peer, cid, err)
7✔
4261

7✔
4262
                        return
7✔
4263
                }
7✔
4264
        }
7✔
4265

7✔
4266
        // The channel_ready message contains the next commitment point we'll
7✔
4267
        // need to create the next commitment state for the remote party. So
7✔
4268
        // we'll insert that into the channel now before passing it along to
7✔
UNCOV
4269
        // other sub-systems.
×
UNCOV
4270
        err = channel.InsertNextRevocation(msg.NextPerCommitmentPoint)
×
UNCOV
4271
        if err != nil {
×
4272
                log.Errorf("unable to insert next commitment point: %v", err)
×
4273
                return
4274
        }
7✔
UNCOV
4275

×
UNCOV
4276
        // Before we can add the channel to the peer, we'll need to ensure that
×
UNCOV
4277
        // we have an initial forwarding policy set.
×
UNCOV
4278
        if err := f.ensureInitialForwardingPolicy(chanID, channel); err != nil {
×
4279
                log.Errorf("Unable to ensure initial forwarding policy: %v",
×
4280
                        err)
4281
        }
4282

4283
        err = peer.AddNewChannel(&lnpeer.NewChannel{
4284
                OpenChannel: channel,
4285
                ChanOpts:    chanOpts,
4286
        }, f.quit)
29✔
4287
        if err != nil {
29✔
4288
                log.Errorf("Unable to add new channel %v with peer %x: %v",
×
4289
                        channel.FundingOutpoint,
×
4290
                        peer.IdentityKey().SerializeCompressed(), err,
×
4291
                )
4292
        }
4293
}
4294

29✔
UNCOV
4295
// handleChannelReadyReceived is called once the remote's channelReady message
×
UNCOV
4296
// is received and processed. At this stage, we must have sent out our
×
UNCOV
4297
// channelReady message, once the remote's channelReady is processed, the
×
4298
// channel is now active, thus we change its state to `addedToGraph` to
4299
// let the channel start handling routing.
29✔
4300
func (f *Manager) handleChannelReadyReceived(channel *channeldb.OpenChannel,
29✔
4301
        scid *lnwire.ShortChannelID, pendingChanID PendingChanID,
29✔
4302
        updateChan chan<- *lnrpc.OpenStatusUpdate) error {
29✔
4303

29✔
UNCOV
4304
        chanID := lnwire.NewChanIDFromOutPoint(channel.FundingOutpoint)
×
UNCOV
4305

×
UNCOV
4306
        // Since we've sent+received funding locked at this point, we
×
UNCOV
4307
        // can clean up the pending musig2 nonce state.
×
UNCOV
4308
        f.nonceMtx.Lock()
×
4309
        delete(f.pendingMusigNonces, chanID)
4310
        f.nonceMtx.Unlock()
4311

4312
        var peerAlias *lnwire.ShortChannelID
4313
        if channel.IsZeroConf() {
4314
                // We'll need to wait until channel_ready has been received and
4315
                // the peer lets us know the alias they want to use for the
4316
                // channel. With this information, we can then construct a
4317
                // ChannelUpdate for them.  If an alias does not yet exist,
4318
                // we'll just return, letting the next iteration of the loop
27✔
4319
                // check again.
27✔
4320
                var defaultAlias lnwire.ShortChannelID
27✔
4321
                chanID := lnwire.NewChanIDFromOutPoint(channel.FundingOutpoint)
27✔
4322
                foundAlias, _ := f.cfg.AliasManager.GetPeerAlias(chanID)
27✔
4323
                if foundAlias == defaultAlias {
27✔
4324
                        return nil
27✔
4325
                }
27✔
4326

27✔
4327
                peerAlias = &foundAlias
27✔
4328
        }
27✔
4329

34✔
4330
        err := f.addToGraph(channel, scid, peerAlias, nil)
7✔
4331
        if err != nil {
7✔
4332
                return fmt.Errorf("failed adding to graph: %w", err)
7✔
4333
        }
7✔
4334

7✔
4335
        // As the channel is now added to the ChannelRouter's topology, the
7✔
4336
        // channel is moved to the next state of the state machine. It will be
7✔
4337
        // moved to the last state (actually deleted from the database) after
7✔
4338
        // the channel is finally announced.
7✔
4339
        err = f.saveChannelOpeningState(
7✔
UNCOV
4340
                &channel.FundingOutpoint, addedToGraph, scid,
×
UNCOV
4341
        )
×
4342
        if err != nil {
4343
                return fmt.Errorf("error setting channel state to"+
7✔
4344
                        " addedToGraph: %w", err)
4345
        }
4346

27✔
4347
        log.Debugf("Channel(%v) with ShortChanID %v: successfully "+
27✔
UNCOV
4348
                "added to graph", chanID, scid)
×
UNCOV
4349

×
4350
        err = fn.MapOptionZ(
4351
                f.cfg.AuxFundingController,
4352
                func(controller AuxFundingController) error {
4353
                        return controller.ChannelReady(
4354
                                lnwallet.NewAuxChanState(channel),
4355
                        )
27✔
4356
                },
27✔
4357
        )
27✔
4358
        if err != nil {
27✔
4359
                return fmt.Errorf("failed notifying aux funding controller "+
×
4360
                        "about channel ready: %w", err)
×
4361
        }
×
4362

4363
        // Give the caller a final update notifying them that the channel is
27✔
4364
        fundingPoint := channel.FundingOutpoint
27✔
4365
        cp := &lnrpc.ChannelPoint{
27✔
4366
                FundingTxid: &lnrpc.ChannelPoint_FundingTxidBytes{
27✔
4367
                        FundingTxidBytes: fundingPoint.Hash[:],
27✔
4368
                },
27✔
UNCOV
4369
                OutputIndex: fundingPoint.Index,
×
UNCOV
4370
        }
×
UNCOV
4371

×
UNCOV
4372
        if updateChan != nil {
×
4373
                upd := &lnrpc.OpenStatusUpdate{
4374
                        Update: &lnrpc.OpenStatusUpdate_ChanOpen{
27✔
UNCOV
4375
                                ChanOpen: &lnrpc.ChannelOpenUpdate{
×
UNCOV
4376
                                        ChannelPoint: cp,
×
UNCOV
4377
                                },
×
4378
                        },
4379
                        PendingChanId: pendingChanID[:],
4380
                }
27✔
4381

27✔
4382
                select {
27✔
4383
                case updateChan <- upd:
27✔
4384
                case <-f.quit:
27✔
4385
                        return ErrFundingManagerShuttingDown
27✔
4386
                }
27✔
4387
        }
27✔
4388

40✔
4389
        return nil
13✔
4390
}
13✔
4391

13✔
4392
// ensureInitialForwardingPolicy ensures that we have an initial forwarding
13✔
4393
// policy set for the given channel. If we don't, we'll fall back to the default
13✔
4394
// values.
13✔
4395
func (f *Manager) ensureInitialForwardingPolicy(chanID lnwire.ChannelID,
13✔
4396
        channel *channeldb.OpenChannel) error {
13✔
4397

13✔
4398
        // Before we can add the channel to the peer, we'll need to ensure that
13✔
4399
        // we have an initial forwarding policy set. This should always be the
13✔
UNCOV
4400
        // case except for a channel that was created with lnd <= 0.15.5 and
×
UNCOV
4401
        // is still pending while updating to this version.
×
4402
        var needDBUpdate bool
4403
        forwardingPolicy, err := f.getInitialForwardingPolicy(chanID)
4404
        if err != nil {
4405
                log.Errorf("Unable to fetch initial forwarding policy, "+
27✔
4406
                        "falling back to default values: %v", err)
4407

4408
                forwardingPolicy = f.defaultForwardingPolicy(
4409
                        channel.LocalChanCfg.ChannelStateBounds,
4410
                )
4411
                needDBUpdate = true
4412
        }
29✔
4413

29✔
4414
        // We only started storing the actual values for MinHTLCOut and MaxHTLC
29✔
4415
        // after 0.16.x, so if a channel was opened with such a version and is
29✔
4416
        // still pending while updating to this version, we'll need to set the
29✔
4417
        // values to the default values.
29✔
4418
        if forwardingPolicy.MinHTLCOut == 0 {
29✔
4419
                forwardingPolicy.MinHTLCOut = channel.LocalChanCfg.MinHTLC
29✔
4420
                needDBUpdate = true
29✔
UNCOV
4421
        }
×
UNCOV
4422
        if forwardingPolicy.MaxHTLC == 0 {
×
UNCOV
4423
                forwardingPolicy.MaxHTLC = channel.LocalChanCfg.MaxPendingAmount
×
UNCOV
4424
                needDBUpdate = true
×
UNCOV
4425
        }
×
UNCOV
4426

×
UNCOV
4427
        // And finally, if we found that the values currently stored aren't
×
UNCOV
4428
        // sufficient for the link, we'll update the database.
×
4429
        if needDBUpdate {
4430
                err := f.saveInitialForwardingPolicy(chanID, forwardingPolicy)
4431
                if err != nil {
4432
                        return fmt.Errorf("unable to update initial "+
4433
                                "forwarding policy: %v", err)
4434
                }
45✔
4435
        }
16✔
4436

16✔
4437
        return nil
16✔
4438
}
45✔
4439

16✔
4440
// chanAnnouncement encapsulates the two authenticated announcements that we
16✔
4441
// send out to the network after a new channel has been created locally.
16✔
4442
type chanAnnouncement struct {
4443
        chanAnn       *lnwire.ChannelAnnouncement1
4444
        chanUpdateAnn *lnwire.ChannelUpdate1
4445
        chanProof     *lnwire.AnnounceSignatures1
45✔
4446
}
16✔
4447

16✔
UNCOV
4448
// newChanAnnouncement creates the authenticated channel announcement messages
×
UNCOV
4449
// required to broadcast a newly created channel to the network. The
×
UNCOV
4450
// announcement is two part: the first part authenticates the existence of the
×
4451
// channel and contains four signatures binding the funding pub keys and
4452
// identity pub keys of both parties to the channel, and the second segment is
4453
// authenticated only by us and contains our directional routing policy for the
29✔
4454
// channel. ourPolicy may be set in order to re-use an existing, non-default
4455
// policy.
4456
func (f *Manager) newChanAnnouncement(localPubKey,
4457
        remotePubKey *btcec.PublicKey, localFundingKey *keychain.KeyDescriptor,
4458
        remoteFundingKey *btcec.PublicKey, shortChanID lnwire.ShortChannelID,
4459
        chanID lnwire.ChannelID, fwdMinHTLC, fwdMaxHTLC lnwire.MilliSatoshi,
4460
        ourPolicy *models.ChannelEdgePolicy,
4461
        chanType channeldb.ChannelType) (*chanAnnouncement, error) {
4462

4463
        chainHash := *f.cfg.Wallet.Cfg.NetParams.GenesisHash
4464

4465
        // The unconditional section of the announcement is the ShortChannelID
4466
        // itself which compactly encodes the location of the funding output
4467
        // within the blockchain.
4468
        chanAnn := &lnwire.ChannelAnnouncement1{
4469
                ShortChannelID: shortChanID,
4470
                Features:       lnwire.NewRawFeatureVector(),
4471
                ChainHash:      chainHash,
4472
        }
4473

4474
        // If this is a taproot channel, then we'll set a special bit in the
4475
        // feature vector to indicate to the routing layer that this needs a
4476
        // slightly different type of validation.
4477
        //
45✔
4478
        // TODO(roasbeef): temp, remove after gossip 1.5
45✔
4479
        if chanType.IsTaproot() {
45✔
4480
                log.Debugf("Applying taproot feature bit to "+
45✔
4481
                        "ChannelAnnouncement for %v", chanID)
45✔
4482

45✔
4483
                chanAnn.Features.Set(
45✔
4484
                        lnwire.SimpleTaprootChannelsRequiredStaging,
45✔
4485
                )
45✔
4486
        }
45✔
4487

45✔
4488
        // The chanFlags field indicates which directed edge of the channel is
45✔
4489
        // being updated within the ChannelUpdateAnnouncement announcement
45✔
4490
        // below. A value of zero means it's the edge of the "first" node and 1
45✔
4491
        // being the other node.
45✔
4492
        var chanFlags lnwire.ChanUpdateChanFlags
45✔
4493

45✔
4494
        // The lexicographical ordering of the two identity public keys of the
45✔
4495
        // nodes indicates which of the nodes is "first". If our serialized
52✔
4496
        // identity key is lower than theirs then we're the "first" node and
7✔
4497
        // second otherwise.
7✔
4498
        selfBytes := localPubKey.SerializeCompressed()
7✔
4499
        remoteBytes := remotePubKey.SerializeCompressed()
7✔
4500
        if bytes.Compare(selfBytes, remoteBytes) == -1 {
7✔
4501
                copy(chanAnn.NodeID1[:], localPubKey.SerializeCompressed())
7✔
4502
                copy(chanAnn.NodeID2[:], remotePubKey.SerializeCompressed())
7✔
4503
                copy(
4504
                        chanAnn.BitcoinKey1[:],
4505
                        localFundingKey.PubKey.SerializeCompressed(),
4506
                )
4507
                copy(
4508
                        chanAnn.BitcoinKey2[:],
45✔
4509
                        remoteFundingKey.SerializeCompressed(),
45✔
4510
                )
45✔
4511

45✔
4512
                // If we're the first node then update the chanFlags to
45✔
4513
                // indicate the "direction" of the update.
45✔
4514
                chanFlags = 0
45✔
4515
        } else {
45✔
4516
                copy(chanAnn.NodeID1[:], remotePubKey.SerializeCompressed())
69✔
4517
                copy(chanAnn.NodeID2[:], localPubKey.SerializeCompressed())
24✔
4518
                copy(
24✔
4519
                        chanAnn.BitcoinKey1[:],
24✔
4520
                        remoteFundingKey.SerializeCompressed(),
24✔
4521
                )
24✔
4522
                copy(
24✔
4523
                        chanAnn.BitcoinKey2[:],
24✔
4524
                        localFundingKey.PubKey.SerializeCompressed(),
24✔
4525
                )
24✔
4526

24✔
4527
                // If we're the second node then update the chanFlags to
24✔
4528
                // indicate the "direction" of the update.
24✔
4529
                chanFlags = 1
24✔
4530
        }
24✔
4531

48✔
4532
        // Our channel update message flags will signal that we support the
24✔
4533
        // max_htlc field.
24✔
4534
        msgFlags := lnwire.ChanUpdateRequiredMaxHtlc
24✔
4535

24✔
4536
        // We announce the channel with the default values. Some of
24✔
4537
        // these values can later be changed by crafting a new ChannelUpdate.
24✔
4538
        chanUpdateAnn := &lnwire.ChannelUpdate1{
24✔
4539
                ShortChannelID: shortChanID,
24✔
4540
                ChainHash:      chainHash,
24✔
4541
                Timestamp:      uint32(time.Now().Unix()),
24✔
4542
                MessageFlags:   msgFlags,
24✔
4543
                ChannelFlags:   chanFlags,
24✔
4544
                TimeLockDelta: uint16(
24✔
4545
                        f.cfg.DefaultRoutingPolicy.TimeLockDelta,
24✔
4546
                ),
24✔
4547
                HtlcMinimumMsat: fwdMinHTLC,
4548
                HtlcMaximumMsat: fwdMaxHTLC,
4549
        }
4550

45✔
4551
        // The caller of newChanAnnouncement is expected to provide the initial
45✔
4552
        // forwarding policy to be announced. If no persisted initial policy
45✔
4553
        // values are found, then we will use the default policy values in the
45✔
4554
        // channel announcement.
45✔
4555
        storedFwdingPolicy, err := f.getInitialForwardingPolicy(chanID)
45✔
4556
        if err != nil && !errors.Is(err, channeldb.ErrChannelNotFound) {
45✔
4557
                return nil, fmt.Errorf("unable to generate channel "+
45✔
4558
                        "update announcement: %w", err)
45✔
4559
        }
45✔
4560

45✔
4561
        switch {
45✔
4562
        case ourPolicy != nil:
45✔
4563
                // If ourPolicy is non-nil, modify the default parameters of the
45✔
4564
                // ChannelUpdate.
45✔
4565
                chanUpdateAnn.MessageFlags = ourPolicy.MessageFlags
45✔
4566
                chanUpdateAnn.ChannelFlags = ourPolicy.ChannelFlags
45✔
4567
                chanUpdateAnn.TimeLockDelta = ourPolicy.TimeLockDelta
45✔
4568
                chanUpdateAnn.HtlcMinimumMsat = ourPolicy.MinHTLC
45✔
4569
                chanUpdateAnn.HtlcMaximumMsat = ourPolicy.MaxHTLC
45✔
4570
                chanUpdateAnn.BaseFee = uint32(ourPolicy.FeeBaseMSat)
45✔
4571
                chanUpdateAnn.FeeRate = uint32(
45✔
4572
                        ourPolicy.FeeProportionalMillionths,
45✔
UNCOV
4573
                )
×
UNCOV
4574

×
UNCOV
4575
        case storedFwdingPolicy != nil:
×
4576
                chanUpdateAnn.BaseFee = uint32(storedFwdingPolicy.BaseFee)
4577
                chanUpdateAnn.FeeRate = uint32(storedFwdingPolicy.FeeRate)
45✔
4578

3✔
4579
        default:
3✔
4580
                log.Infof("No channel forwarding policy specified for channel "+
3✔
4581
                        "announcement of ChannelID(%v). "+
3✔
4582
                        "Assuming default fee parameters.", chanID)
3✔
4583
                chanUpdateAnn.BaseFee = uint32(
3✔
4584
                        f.cfg.DefaultRoutingPolicy.BaseFee,
3✔
4585
                )
3✔
4586
                chanUpdateAnn.FeeRate = uint32(
3✔
4587
                        f.cfg.DefaultRoutingPolicy.FeeRate,
3✔
4588
                )
3✔
4589
        }
3✔
4590

4591
        // With the channel update announcement constructed, we'll generate a
45✔
4592
        // signature that signs a double-sha digest of the announcement.
45✔
4593
        // This'll serve to authenticate this announcement and any other future
45✔
4594
        // updates we may send.
UNCOV
4595
        chanUpdateMsg, err := chanUpdateAnn.DataToSign()
×
UNCOV
4596
        if err != nil {
×
4597
                return nil, err
×
4598
        }
×
UNCOV
4599
        sig, err := f.cfg.SignMessage(f.cfg.IDKeyLoc, chanUpdateMsg, true)
×
UNCOV
4600
        if err != nil {
×
4601
                return nil, fmt.Errorf("unable to generate channel "+
×
4602
                        "update announcement signature: %w", err)
×
4603
        }
×
UNCOV
4604
        chanUpdateAnn.Signature, err = lnwire.NewSigFromSignature(sig)
×
4605
        if err != nil {
4606
                return nil, fmt.Errorf("unable to generate channel "+
4607
                        "update announcement signature: %w", err)
4608
        }
4609

4610
        // The channel existence proofs itself is currently announced in
4611
        // distinct message. In order to properly authenticate this message, we
45✔
4612
        // need two signatures: one under the identity public key used which
45✔
UNCOV
4613
        // signs the message itself and another signature of the identity
×
UNCOV
4614
        // public key under the funding key itself.
×
4615
        //
45✔
4616
        // TODO(roasbeef): use SignAnnouncement here instead?
45✔
UNCOV
4617
        chanAnnMsg, err := chanAnn.DataToSign()
×
UNCOV
4618
        if err != nil {
×
4619
                return nil, err
×
4620
        }
45✔
4621
        nodeSig, err := f.cfg.SignMessage(f.cfg.IDKeyLoc, chanAnnMsg, true)
45✔
UNCOV
4622
        if err != nil {
×
4623
                return nil, fmt.Errorf("unable to generate node "+
×
4624
                        "signature for channel announcement: %w", err)
×
4625
        }
4626
        bitcoinSig, err := f.cfg.SignMessage(
4627
                localFundingKey.KeyLocator, chanAnnMsg, true,
4628
        )
4629
        if err != nil {
4630
                return nil, fmt.Errorf("unable to generate bitcoin "+
4631
                        "signature for node public key: %w", err)
4632
        }
4633

45✔
4634
        // Finally, we'll generate the announcement proof which we'll use to
45✔
UNCOV
4635
        // provide the other side with the necessary signatures required to
×
UNCOV
4636
        // allow them to reconstruct the full channel announcement.
×
4637
        proof := &lnwire.AnnounceSignatures1{
45✔
4638
                ChannelID:      chanID,
45✔
UNCOV
4639
                ShortChannelID: shortChanID,
×
UNCOV
4640
        }
×
UNCOV
4641
        proof.NodeSignature, err = lnwire.NewSigFromSignature(nodeSig)
×
4642
        if err != nil {
45✔
4643
                return nil, err
45✔
4644
        }
45✔
4645
        proof.BitcoinSignature, err = lnwire.NewSigFromSignature(bitcoinSig)
45✔
UNCOV
4646
        if err != nil {
×
4647
                return nil, err
×
4648
        }
×
4649

4650
        return &chanAnnouncement{
4651
                chanAnn:       chanAnn,
4652
                chanUpdateAnn: chanUpdateAnn,
4653
                chanProof:     proof,
45✔
4654
        }, nil
45✔
4655
}
45✔
4656

45✔
4657
// announceChannel announces a newly created channel to the rest of the network
45✔
4658
// by crafting the two authenticated announcements required for the peers on
45✔
UNCOV
4659
// the network to recognize the legitimacy of the channel. The crafted
×
UNCOV
4660
// announcements are then sent to the channel router to handle broadcasting to
×
4661
// the network during its next trickle.
45✔
4662
// This method is synchronous and will return when all the network requests
45✔
UNCOV
4663
// finish, either successfully or with an error.
×
UNCOV
4664
func (f *Manager) announceChannel(localIDKey, remoteIDKey *btcec.PublicKey,
×
4665
        localFundingKey *keychain.KeyDescriptor,
4666
        remoteFundingKey *btcec.PublicKey, shortChanID lnwire.ShortChannelID,
45✔
4667
        chanID lnwire.ChannelID, chanType channeldb.ChannelType) error {
45✔
4668

45✔
4669
        // First, we'll create the batch of announcements to be sent upon
45✔
4670
        // initial channel creation. This includes the channel announcement
45✔
4671
        // itself, the channel update announcement, and our half of the channel
4672
        // proof needed to fully authenticate the channel.
4673
        //
4674
        // We can pass in zeroes for the min and max htlc policy, because we
4675
        // only use the channel announcement message from the returned struct.
4676
        ann, err := f.newChanAnnouncement(
4677
                localIDKey, remoteIDKey, localFundingKey, remoteFundingKey,
4678
                shortChanID, chanID, 0, 0, nil, chanType,
4679
        )
4680
        if err != nil {
4681
                log.Errorf("can't generate channel announcement: %v", err)
4682
                return err
4683
        }
19✔
4684

19✔
4685
        // We only send the channel proof announcement and the node announcement
19✔
4686
        // because addToGraph previously sent the ChannelAnnouncement and
19✔
4687
        // the ChannelUpdate announcement messages. The channel proof and node
19✔
4688
        // announcements are broadcast to the greater network.
19✔
4689
        errChan := f.cfg.SendAnnouncement(ann.chanProof)
19✔
4690
        select {
19✔
4691
        case err := <-errChan:
19✔
4692
                if err != nil {
19✔
4693
                        if graph.IsError(err, graph.ErrOutdated,
19✔
4694
                                graph.ErrIgnored) {
19✔
4695

19✔
4696
                                log.Debugf("Graph rejected "+
19✔
4697
                                        "AnnounceSignatures: %v", err)
×
UNCOV
4698
                        } else {
×
UNCOV
4699
                                log.Errorf("Unable to send channel "+
×
4700
                                        "proof: %v", err)
4701
                                return err
4702
                        }
4703
                }
4704

4705
        case <-f.quit:
19✔
4706
                return ErrFundingManagerShuttingDown
19✔
4707
        }
19✔
4708

22✔
4709
        // Now that the channel is announced to the network, we will also
3✔
4710
        // obtain and send a node announcement. This is done since a node
3✔
UNCOV
4711
        // announcement is only accepted after a channel is known for that
×
UNCOV
4712
        // particular node, and this might be our first channel.
×
UNCOV
4713
        nodeAnn, err := f.cfg.CurrentNodeAnnouncement()
×
4714
        if err != nil {
3✔
4715
                log.Errorf("can't generate node announcement: %v", err)
3✔
4716
                return err
3✔
4717
        }
3✔
4718

3✔
4719
        errChan = f.cfg.SendAnnouncement(&nodeAnn)
4720
        select {
UNCOV
4721
        case err := <-errChan:
×
UNCOV
4722
                if err != nil {
×
4723
                        if graph.IsError(err, graph.ErrOutdated,
4724
                                graph.ErrIgnored) {
4725

4726
                                log.Debugf("Graph rejected "+
4727
                                        "NodeAnnouncement1: %v", err)
4728
                        } else {
4729
                                log.Errorf("Unable to send node "+
19✔
4730
                                        "announcement: %v", err)
19✔
4731
                                return err
×
4732
                        }
×
UNCOV
4733
                }
×
4734

4735
        case <-f.quit:
19✔
4736
                return ErrFundingManagerShuttingDown
19✔
4737
        }
19✔
4738

22✔
4739
        return nil
3✔
4740
}
6✔
4741

3✔
4742
// InitFundingWorkflow sends a message to the funding manager instructing it
3✔
4743
// to initiate a single funder workflow with the source peer.
3✔
4744
func (f *Manager) InitFundingWorkflow(msg *InitFundingMsg) {
3✔
UNCOV
4745
        f.fundingRequests <- msg
×
UNCOV
4746
}
×
UNCOV
4747

×
UNCOV
4748
// getUpfrontShutdownScript takes a user provided script and a getScript
×
4749
// function which can be used to generate an upfront shutdown script. If our
4750
// peer does not support the feature, this function will error if a non-zero
UNCOV
4751
// script was provided by the user, and return an empty script otherwise. If
×
UNCOV
4752
// our peer does support the feature, we will return the user provided script
×
4753
// if non-zero, or a freshly generated script if our node is configured to set
4754
// upfront shutdown scripts automatically.
4755
func getUpfrontShutdownScript(enableUpfrontShutdown bool, peer lnpeer.Peer,
19✔
4756
        script lnwire.DeliveryAddress,
4757
        getScript func(bool) (lnwire.DeliveryAddress, error)) (lnwire.DeliveryAddress,
4758
        error) {
4759

4760
        // Check whether the remote peer supports upfront shutdown scripts.
60✔
4761
        remoteUpfrontShutdown := peer.RemoteFeatures().HasFeature(
60✔
4762
                lnwire.UpfrontShutdownScriptOptional,
60✔
4763
        )
4764

4765
        // If the peer does not support upfront shutdown scripts, and one has been
4766
        // provided, return an error because the feature is not supported.
4767
        if !remoteUpfrontShutdown && len(script) != 0 {
4768
                return nil, errUpfrontShutdownScriptNotSupported
4769
        }
4770

4771
        // If the peer does not support upfront shutdown, return an empty address.
4772
        if !remoteUpfrontShutdown {
4773
                return nil, nil
4774
        }
113✔
4775

113✔
4776
        // If the user has provided an script and the peer supports the feature,
113✔
4777
        // return it. Note that user set scripts override the enable upfront
113✔
4778
        // shutdown flag.
113✔
4779
        if len(script) > 0 {
113✔
4780
                return script, nil
113✔
4781
        }
113✔
4782

113✔
4783
        // If we do not have setting of upfront shutdown script enabled, return
114✔
4784
        // an empty script.
1✔
4785
        if !enableUpfrontShutdown {
1✔
4786
                return nil, nil
4787
        }
4788

217✔
4789
        // We can safely send a taproot address iff, both sides have negotiated
105✔
4790
        // the shutdown-any-segwit feature.
105✔
4791
        taprootOK := peer.RemoteFeatures().HasFeature(lnwire.ShutdownAnySegwitOptional) &&
4792
                peer.LocalFeatures().HasFeature(lnwire.ShutdownAnySegwitOptional)
4793

4794
        return getScript(taprootOK)
4795
}
12✔
4796

5✔
4797
// handleInitFundingMsg creates a channel reservation within the daemon's
5✔
4798
// wallet, then sends a funding request to the remote peer kicking off the
4799
// funding workflow.
4800
func (f *Manager) handleInitFundingMsg(msg *InitFundingMsg) {
4801
        var (
9✔
4802
                peerKey        = msg.Peer.IdentityKey()
4✔
4803
                localAmt       = msg.LocalFundingAmt
4✔
4804
                baseFee        = msg.BaseFee
4805
                feeRate        = msg.FeeRate
4806
                minHtlcIn      = msg.MinHtlcIn
4807
                remoteCsvDelay = msg.RemoteCsvDelay
1✔
4808
                maxValue       = msg.MaxValueInFlight
1✔
4809
                maxHtlcs       = msg.MaxHtlcs
1✔
4810
                maxCSV         = msg.MaxLocalCsv
1✔
4811
                chanReserve    = msg.RemoteChanReserve
4812
                outpoints      = msg.Outpoints
4813
        )
4814

4815
        // If no maximum CSV delay was set for this channel, we use our default
4816
        // value.
60✔
4817
        if maxCSV == 0 {
60✔
4818
                maxCSV = f.cfg.MaxLocalCSVDelay
60✔
4819
        }
60✔
4820

60✔
4821
        log.Infof("Initiating fundingRequest(local_amt=%v "+
60✔
4822
                "(subtract_fees=%v), push_amt=%v, chain_hash=%v, peer=%x, "+
60✔
4823
                "min_confs=%v)", localAmt, msg.SubtractFees, msg.PushAmt,
60✔
4824
                msg.ChainHash, peerKey.SerializeCompressed(), msg.MinConfs)
60✔
4825

60✔
4826
        // We set the channel flags to indicate whether we want this channel to
60✔
4827
        // be announced to the network.
60✔
4828
        var channelFlags lnwire.FundingFlag
60✔
4829
        if !msg.Private {
60✔
4830
                // This channel will be announced.
60✔
4831
                channelFlags = lnwire.FFAnnounceChannel
60✔
4832
        }
60✔
4833

120✔
4834
        // If the caller specified their own channel ID, then we'll use that.
60✔
4835
        // Otherwise we'll generate a fresh one as normal.  This will be used
60✔
4836
        // to track this reservation throughout its lifetime.
4837
        var chanID PendingChanID
60✔
4838
        if msg.PendingChanID == zeroID {
60✔
4839
                chanID = f.nextPendingChanID()
60✔
4840
        } else {
60✔
4841
                // If the user specified their own pending channel ID, then
60✔
4842
                // we'll ensure it doesn't collide with any existing pending
60✔
4843
                // channel ID.
60✔
4844
                chanID = msg.PendingChanID
60✔
4845
                if _, err := f.getReservationCtx(peerKey, chanID); err == nil {
115✔
4846
                        msg.Err <- fmt.Errorf("pendingChannelID(%x) "+
55✔
4847
                                "already present", chanID[:])
55✔
4848
                        return
55✔
4849
                }
4850
        }
4851

4852
        // Check whether the peer supports upfront shutdown, and get an address
4853
        // which should be used (either a user specified address or a new
60✔
4854
        // address from the wallet if our node is configured to set shutdown
120✔
4855
        // address by default).
60✔
4856
        shutdown, err := getUpfrontShutdownScript(
63✔
4857
                f.cfg.EnableUpfrontShutdown, msg.Peer, msg.ShutdownScript,
3✔
4858
                f.selectShutdownScript,
3✔
4859
        )
3✔
4860
        if err != nil {
3✔
4861
                msg.Err <- err
3✔
4862
                return
×
4863
        }
×
UNCOV
4864

×
UNCOV
4865
        // Initialize a funding reservation with the local wallet. If the
×
4866
        // wallet doesn't have enough funds to commit to this channel, then the
4867
        // request will fail, and be aborted.
4868
        //
4869
        // Before we init the channel, we'll also check to see what commitment
4870
        // format we can use with this peer. This is dependent on *both* us and
60✔
4871
        // the remote peer are signaling the proper feature bit.
120✔
4872
        chanType, commitType, err := negotiateCommitmentType(
60✔
4873
                msg.ChannelType, msg.Peer.LocalFeatures(),
63✔
4874
                msg.Peer.RemoteFeatures(),
3✔
4875
        )
3✔
4876
        if err != nil {
4877
                log.Errorf("channel type negotiation failed: %v", err)
4878
                msg.Err <- err
4879
                return
4880
        }
4881

4882
        var (
4883
                zeroConf bool
60✔
4884
                scid     bool
60✔
4885
        )
60✔
4886

60✔
4887
        if chanType != nil {
60✔
UNCOV
4888
                // Check if the returned chanType includes either the zero-conf
×
UNCOV
4889
                // or scid-alias bits.
×
UNCOV
4890
                featureVec := lnwire.RawFeatureVector(*chanType)
×
4891
                zeroConf = featureVec.IsSet(lnwire.ZeroConfRequired)
4892
                scid = featureVec.IsSet(lnwire.ScidAliasRequired)
4893

4894
                // The option-scid-alias channel type for a public channel is
4895
                // disallowed.
4896
                if scid && !msg.Private {
4897
                        err = fmt.Errorf("option-scid-alias chantype for " +
4898
                                "public channel")
4899
                        log.Error(err)
60✔
4900
                        msg.Err <- err
60✔
4901

60✔
4902
                        return
60✔
4903
                }
63✔
4904
        }
3✔
4905

3✔
4906
        // First, we'll query the fee estimator for a fee that should get the
3✔
4907
        // commitment transaction confirmed by the next few blocks (conf target
3✔
4908
        // of 3). We target the near blocks here to ensure that we'll be able
4909
        // to execute a timely unilateral channel closure if needed.
60✔
4910
        commitFeePerKw, err := f.cfg.FeeEstimator.EstimateFeePerKW(3)
60✔
4911
        if err != nil {
60✔
4912
                msg.Err <- err
60✔
4913
                return
60✔
4914
        }
67✔
4915

7✔
4916
        // For anchor channels cap the initial commit fee rate at our defined
7✔
4917
        // maximum.
7✔
4918
        if commitType.HasAnchors() &&
7✔
4919
                commitFeePerKw > f.cfg.MaxAnchorsCommitFeeRate {
7✔
4920

7✔
4921
                commitFeePerKw = f.cfg.MaxAnchorsCommitFeeRate
7✔
4922
        }
7✔
4923

7✔
UNCOV
4924
        var scidFeatureVal bool
×
UNCOV
4925
        if hasFeatures(
×
UNCOV
4926
                msg.Peer.LocalFeatures(), msg.Peer.RemoteFeatures(),
×
UNCOV
4927
                lnwire.ScidAliasOptional,
×
UNCOV
4928
        ) {
×
UNCOV
4929

×
UNCOV
4930
                scidFeatureVal = true
×
4931
        }
4932

4933
        // At this point, if we have an AuxFundingController active, we'll check
4934
        // to see if we have a special tapscript root to use in our MuSig2
4935
        // funding output.
4936
        tapscriptRoot, err := fn.MapOptionZ(
4937
                f.cfg.AuxFundingController,
60✔
4938
                func(c AuxFundingController) AuxTapscriptResult {
60✔
4939
                        return c.DeriveTapscriptRoot(chanID)
×
4940
                },
×
UNCOV
4941
        ).Unpack()
×
4942
        if err != nil {
4943
                err = fmt.Errorf("error deriving tapscript root: %w", err)
4944
                log.Error(err)
4945
                msg.Err <- err
60✔
4946

67✔
4947
                return
7✔
4948
        }
7✔
4949

7✔
4950
        req := &lnwallet.InitFundingReserveMsg{
4951
                ChainHash:         &msg.ChainHash,
60✔
4952
                PendingChanID:     chanID,
60✔
4953
                NodeID:            peerKey,
60✔
4954
                NodeAddr:          msg.Peer.Address(),
60✔
4955
                SubtractFees:      msg.SubtractFees,
66✔
4956
                LocalFundingAmt:   localAmt,
6✔
4957
                RemoteFundingAmt:  0,
6✔
4958
                FundUpToMaxAmt:    msg.FundUpToMaxAmt,
6✔
4959
                MinFundAmt:        msg.MinFundAmt,
4960
                RemoteChanReserve: chanReserve,
4961
                Outpoints:         outpoints,
4962
                CommitFeePerKw:    commitFeePerKw,
4963
                FundingFeePerKw:   msg.FundingFeePerKw,
60✔
4964
                PushMSat:          msg.PushAmt,
60✔
4965
                Flags:             channelFlags,
60✔
UNCOV
4966
                MinConfs:          msg.MinConfs,
×
UNCOV
4967
                CommitType:        commitType,
×
4968
                ChanFunder:        msg.ChanFunder,
4969
                // Unconfirmed Utxos which are marked by the sweeper subsystem
60✔
UNCOV
4970
                // are excluded from the coin selection because they are not
×
UNCOV
4971
                // final and can be RBFed by the sweeper subsystem.
×
UNCOV
4972
                AllowUtxoForFunding: func(u lnwallet.Utxo) bool {
×
UNCOV
4973
                        // Utxos with at least 1 confirmation are safe to use
×
UNCOV
4974
                        // for channel openings because they don't bare the risk
×
UNCOV
4975
                        // of being replaced (BIP 125 RBF).
×
4976
                        if u.Confirmations > 0 {
4977
                                return true
60✔
4978
                        }
60✔
4979

60✔
4980
                        // Query the sweeper storage to make sure we don't use
60✔
4981
                        // an unconfirmed utxo still in use by the sweeper
60✔
4982
                        // subsystem.
60✔
4983
                        return !f.cfg.IsSweeperOutpoint(u.OutPoint)
60✔
4984
                },
60✔
4985
                ZeroConf:         zeroConf,
60✔
4986
                OptionScidAlias:  scid,
60✔
4987
                ScidAliasFeature: scidFeatureVal,
60✔
4988
                Memo:             msg.Memo,
60✔
4989
                TapscriptRoot:    tapscriptRoot,
60✔
4990
        }
60✔
4991

60✔
4992
        reservation, err := f.cfg.Wallet.InitChannelReservation(req)
60✔
4993
        if err != nil {
60✔
4994
                msg.Err <- err
60✔
4995
                return
60✔
4996
        }
60✔
4997

60✔
4998
        if zeroConf {
60✔
4999
                // Store the alias for zero-conf channels in the underlying
121✔
5000
                // partial channel state.
61✔
5001
                aliasScid, err := f.cfg.AliasManager.RequestAlias()
61✔
5002
                if err != nil {
61✔
5003
                        msg.Err <- err
64✔
5004
                        return
3✔
5005
                }
3✔
5006

5007
                reservation.AddAlias(aliasScid)
5008
        }
5009

5010
        // Set our upfront shutdown address in the existing reservation.
61✔
5011
        reservation.SetOurUpfrontShutdown(shutdown)
5012

5013
        // Now that we have successfully reserved funds for this channel in the
5014
        // wallet, we can fetch the final channel capacity. This is done at
5015
        // this point since the final capacity might change in case of
5016
        // SubtractFees=true.
5017
        capacity := reservation.Capacity()
5018

5019
        log.Infof("Target commit tx sat/kw for pendingID(%x): %v", chanID,
60✔
5020
                int64(commitFeePerKw))
63✔
5021

3✔
5022
        // If the remote CSV delay was not set in the open channel request,
3✔
5023
        // we'll use the RequiredRemoteDelay closure to compute the delay we
3✔
5024
        // require given the total amount of funds within the channel.
5025
        if remoteCsvDelay == 0 {
65✔
5026
                remoteCsvDelay = f.cfg.RequiredRemoteDelay(capacity)
5✔
5027
        }
5✔
5028

5✔
5029
        // If no minimum HTLC value was specified, use the default one.
5✔
UNCOV
5030
        if minHtlcIn == 0 {
×
UNCOV
5031
                minHtlcIn = f.cfg.DefaultMinHtlcIn
×
UNCOV
5032
        }
×
5033

5034
        // If no max value was specified, use the default one.
5✔
5035
        if maxValue == 0 {
5036
                maxValue = f.cfg.RequiredRemoteMaxValue(capacity)
5037
        }
5038

60✔
5039
        if maxHtlcs == 0 {
60✔
5040
                maxHtlcs = f.cfg.RequiredRemoteMaxHTLCs(capacity)
60✔
5041
        }
60✔
5042

60✔
5043
        // Once the reservation has been created, and indexed, queue a funding
60✔
5044
        // request to the remote peer, kicking off the funding workflow.
60✔
5045
        ourContribution := reservation.OurContribution()
60✔
5046

60✔
5047
        // Prepare the optional channel fee values from the initFundingMsg. If
60✔
5048
        // useBaseFee or useFeeRate are false the client did not provide fee
60✔
5049
        // values hence we assume default fee settings from the config.
60✔
5050
        forwardingPolicy := f.defaultForwardingPolicy(
60✔
5051
                ourContribution.ChannelStateBounds,
60✔
5052
        )
119✔
5053
        if baseFee != nil {
59✔
5054
                forwardingPolicy.BaseFee = lnwire.MilliSatoshi(*baseFee)
59✔
5055
        }
5056

5057
        if feeRate != nil {
119✔
5058
                forwardingPolicy.FeeRate = lnwire.MilliSatoshi(*feeRate)
59✔
5059
        }
59✔
5060

5061
        // Fetch our dust limit which is part of the default channel
5062
        // constraints, and log it.
119✔
5063
        ourDustLimit := ourContribution.DustLimit
59✔
5064

59✔
5065
        log.Infof("Dust limit for pendingID(%x): %v", chanID, ourDustLimit)
5066

120✔
5067
        // If the channel reserve is not specified, then we calculate an
60✔
5068
        // appropriate amount here.
60✔
5069
        if chanReserve == 0 {
5070
                chanReserve = f.cfg.RequiredRemoteChanReserve(
5071
                        capacity, ourDustLimit,
5072
                )
60✔
5073
        }
60✔
5074

60✔
5075
        // If a pending channel map for this peer isn't already created, then
60✔
5076
        // we create one, ultimately allowing us to track this pending
60✔
5077
        // reservation within the target peer.
60✔
5078
        peerIDKey := newSerializedKey(peerKey)
60✔
5079
        f.resMtx.Lock()
60✔
5080
        if _, ok := f.activeReservations[peerIDKey]; !ok {
64✔
5081
                f.activeReservations[peerIDKey] = make(pendingChannels)
4✔
5082
        }
4✔
5083

5084
        resCtx := &reservationWithCtx{
64✔
5085
                chanAmt:           capacity,
4✔
5086
                forwardingPolicy:  *forwardingPolicy,
4✔
5087
                remoteCsvDelay:    remoteCsvDelay,
5088
                remoteMinHtlc:     minHtlcIn,
5089
                remoteMaxValue:    maxValue,
5090
                remoteMaxHtlcs:    maxHtlcs,
60✔
5091
                remoteChanReserve: chanReserve,
60✔
5092
                maxLocalCsv:       maxCSV,
60✔
5093
                channelType:       chanType,
60✔
5094
                reservation:       reservation,
60✔
5095
                peer:              msg.Peer,
60✔
5096
                updates:           msg.Updates,
116✔
5097
                err:               msg.Err,
56✔
5098
        }
56✔
5099
        f.activeReservations[peerIDKey][chanID] = resCtx
56✔
5100
        f.resMtx.Unlock()
56✔
5101

5102
        // Update the timestamp once the InitFundingMsg has been handled.
5103
        defer resCtx.updateTimestamp()
5104

5105
        // Check the sanity of the selected channel constraints.
60✔
5106
        bounds := &channeldb.ChannelStateBounds{
60✔
5107
                ChanReserve:      chanReserve,
113✔
5108
                MaxPendingAmount: maxValue,
53✔
5109
                MinHTLC:          minHtlcIn,
53✔
5110
                MaxAcceptedHtlcs: maxHtlcs,
5111
        }
60✔
5112
        commitParams := &channeldb.CommitmentParams{
60✔
5113
                DustLimit: ourDustLimit,
60✔
5114
                CsvDelay:  remoteCsvDelay,
60✔
5115
        }
60✔
5116
        err = lnwallet.VerifyConstraints(
60✔
5117
                bounds, commitParams, resCtx.maxLocalCsv, capacity,
60✔
5118
        )
60✔
5119
        if err != nil {
60✔
5120
                _, reserveErr := f.cancelReservationCtx(peerKey, chanID, false)
60✔
5121
                if reserveErr != nil {
60✔
5122
                        log.Errorf("unable to cancel reservation: %v",
60✔
5123
                                reserveErr)
60✔
5124
                }
60✔
5125

60✔
5126
                msg.Err <- err
60✔
5127
                return
60✔
5128
        }
60✔
5129

60✔
5130
        // When opening a script enforced channel lease, include the required
60✔
5131
        // expiry TLV record in our proposal.
60✔
5132
        var leaseExpiry *lnwire.LeaseExpiry
60✔
5133
        if commitType == lnwallet.CommitmentTypeScriptEnforcedLease {
60✔
5134
                leaseExpiry = new(lnwire.LeaseExpiry)
60✔
5135
                *leaseExpiry = lnwire.LeaseExpiry(reservation.LeaseExpiry())
60✔
5136
        }
60✔
5137

60✔
5138
        log.Infof("Starting funding workflow with %v for pending_id(%x), "+
60✔
5139
                "committype=%v", msg.Peer.Address(), chanID, commitType)
60✔
5140

60✔
5141
        reservation.SetState(lnwallet.SentOpenChannel)
60✔
5142

60✔
5143
        fundingOpen := lnwire.OpenChannel{
60✔
5144
                ChainHash:             *f.cfg.Wallet.Cfg.NetParams.GenesisHash,
60✔
5145
                PendingChannelID:      chanID,
60✔
5146
                FundingAmount:         capacity,
62✔
5147
                PushAmount:            msg.PushAmt,
2✔
5148
                DustLimit:             ourDustLimit,
2✔
UNCOV
5149
                MaxValueInFlight:      maxValue,
×
UNCOV
5150
                ChannelReserve:        chanReserve,
×
UNCOV
5151
                HtlcMinimum:           minHtlcIn,
×
5152
                FeePerKiloWeight:      uint32(commitFeePerKw),
5153
                CsvDelay:              remoteCsvDelay,
2✔
5154
                MaxAcceptedHTLCs:      maxHtlcs,
2✔
5155
                FundingKey:            ourContribution.MultiSigKey.PubKey,
5156
                RevocationPoint:       ourContribution.RevocationBasePoint.PubKey,
5157
                PaymentPoint:          ourContribution.PaymentBasePoint.PubKey,
5158
                HtlcPoint:             ourContribution.HtlcBasePoint.PubKey,
5159
                DelayedPaymentPoint:   ourContribution.DelayBasePoint.PubKey,
58✔
5160
                FirstCommitmentPoint:  ourContribution.FirstCommitmentPoint,
61✔
5161
                ChannelFlags:          channelFlags,
3✔
5162
                UpfrontShutdownScript: shutdown,
3✔
5163
                ChannelType:           chanType,
3✔
5164
                LeaseExpiry:           leaseExpiry,
5165
        }
58✔
5166

58✔
5167
        if commitType.IsTaproot() {
58✔
5168
                fundingOpen.LocalNonce = lnwire.SomeMusig2Nonce(
58✔
5169
                        ourContribution.LocalNonce.PubNonce,
58✔
5170
                )
58✔
5171
        }
58✔
5172

58✔
5173
        if err := msg.Peer.SendMessage(true, &fundingOpen); err != nil {
58✔
5174
                e := fmt.Errorf("unable to send funding request message: %w",
58✔
5175
                        err)
58✔
5176
                log.Errorf(e.Error())
58✔
5177

58✔
5178
                // Since we were unable to send the initial message to the peer
58✔
5179
                // and start the funding flow, we'll cancel this reservation.
58✔
5180
                _, err := f.cancelReservationCtx(peerKey, chanID, false)
58✔
5181
                if err != nil {
58✔
5182
                        log.Errorf("unable to cancel reservation: %v", err)
58✔
5183
                }
58✔
5184

58✔
5185
                msg.Err <- e
58✔
5186
                return
58✔
5187
        }
58✔
5188
}
58✔
5189

58✔
5190
// handleWarningMsg processes the warning which was received from remote peer.
58✔
5191
func (f *Manager) handleWarningMsg(peer lnpeer.Peer, msg *lnwire.Warning) {
58✔
5192
        log.Warnf("received warning message from peer %x: %v",
58✔
5193
                peer.IdentityKey().SerializeCompressed(), msg.Warning())
58✔
5194
}
63✔
5195

5✔
5196
// handleErrorMsg processes the error which was received from remote peer,
5✔
5197
// depending on the type of error we should do different clean up steps and
5✔
5198
// inform the user about it.
5✔
5199
func (f *Manager) handleErrorMsg(peer lnpeer.Peer, msg *lnwire.Error) {
5200
        chanID := msg.ChanID
58✔
UNCOV
5201
        peerKey := peer.IdentityKey()
×
UNCOV
5202

×
UNCOV
5203
        // First, we'll attempt to retrieve and cancel the funding workflow
×
UNCOV
5204
        // that this error was tied to. If we're unable to do so, then we'll
×
UNCOV
5205
        // exit early as this was an unwarranted error.
×
UNCOV
5206
        resCtx, err := f.cancelReservationCtx(peerKey, chanID, true)
×
UNCOV
5207
        if err != nil {
×
5208
                log.Warnf("Received error for non-existent funding "+
×
5209
                        "flow: %v (%v)", err, msg.Error())
×
5210
                return
×
5211
        }
UNCOV
5212

×
UNCOV
5213
        // If we did indeed find the funding workflow, then we'll return the
×
5214
        // error back to the caller (if any), and cancel the workflow itself.
5215
        fundingErr := fmt.Errorf("received funding error from %x: %v",
5216
                peerKey.SerializeCompressed(), msg.Error(),
5217
        )
5218
        log.Errorf(fundingErr.Error())
44✔
5219

44✔
5220
        // If this was a PSBT funding flow, the remote likely timed out because
44✔
5221
        // we waited too long. Return a nice error message to the user in that
44✔
5222
        // case so the user knows what's the problem.
5223
        if resCtx.reservation.IsPsbt() {
5224
                fundingErr = fmt.Errorf("%w: %v", chanfunding.ErrRemoteCanceled,
5225
                        fundingErr)
5226
        }
3✔
5227

3✔
5228
        resCtx.err <- fundingErr
3✔
5229
}
3✔
5230

3✔
5231
// pruneZombieReservations loops through all pending reservations and fails the
3✔
5232
// funding flow for any reservations that have not been updated since the
3✔
5233
// ReservationTimeout and are not locked waiting for the funding transaction.
3✔
5234
func (f *Manager) pruneZombieReservations() {
3✔
UNCOV
5235
        zombieReservations := make(pendingChannels)
×
UNCOV
5236

×
UNCOV
5237
        f.resMtx.RLock()
×
UNCOV
5238
        for _, pendingReservations := range f.activeReservations {
×
5239
                for pendingChanID, resCtx := range pendingReservations {
5240
                        if resCtx.isLocked() {
5241
                                continue
5242
                        }
3✔
5243

3✔
5244
                        // We don't want to expire PSBT funding reservations.
3✔
5245
                        // These reservations are always initiated by us and the
3✔
5246
                        // remote peer is likely going to cancel them after some
3✔
5247
                        // idle time anyway. So no need for us to also prune
3✔
5248
                        // them.
3✔
5249
                        sinceLastUpdate := time.Since(resCtx.lastUpdated)
3✔
5250
                        isExpired := sinceLastUpdate > f.cfg.ReservationTimeout
6✔
5251
                        if !resCtx.reservation.IsPsbt() && isExpired {
3✔
5252
                                zombieReservations[pendingChanID] = resCtx
3✔
5253
                        }
3✔
5254
                }
5255
        }
3✔
5256
        f.resMtx.RUnlock()
5257

5258
        for pendingChanID, resCtx := range zombieReservations {
5259
                err := fmt.Errorf("reservation timed out waiting for peer "+
5260
                        "(peer_id:%x, chan_id:%x)",
5261
                        resCtx.peer.IdentityKey().SerializeCompressed(),
6✔
5262
                        pendingChanID[:])
6✔
5263
                log.Warnf(err.Error())
6✔
5264

6✔
5265
                chanID := lnwire.NewChanIDFromOutPoint(
12✔
5266
                        *resCtx.reservation.FundingOutpoint(),
12✔
5267
                )
6✔
UNCOV
5268

×
5269
                // Create channel identifier and set the channel ID.
5270
                cid := newChanIdentifier(pendingChanID)
5271
                cid.setChanID(chanID)
5272

5273
                f.failFundingFlow(resCtx.peer, cid, err)
5274
        }
5275
}
5276

6✔
5277
// cancelReservationCtx does all needed work in order to securely cancel the
6✔
5278
// reservation.
12✔
5279
func (f *Manager) cancelReservationCtx(peerKey *btcec.PublicKey,
6✔
5280
        pendingChanID PendingChanID,
6✔
5281
        byRemote bool) (*reservationWithCtx, error) {
5282

5283
        log.Infof("Cancelling funding reservation for node_key=%x, "+
6✔
5284
                "chan_id=%x", peerKey.SerializeCompressed(), pendingChanID[:])
6✔
5285

12✔
5286
        peerIDKey := newSerializedKey(peerKey)
6✔
5287
        f.resMtx.Lock()
6✔
5288
        defer f.resMtx.Unlock()
6✔
5289

6✔
5290
        nodeReservations, ok := f.activeReservations[peerIDKey]
6✔
5291
        if !ok {
6✔
5292
                // No reservations for this node.
6✔
5293
                return nil, fmt.Errorf("no active reservations for peer(%x)",
6✔
5294
                        peerIDKey[:])
6✔
5295
        }
6✔
5296

6✔
5297
        ctx, ok := nodeReservations[pendingChanID]
6✔
5298
        if !ok {
6✔
5299
                return nil, fmt.Errorf("unknown channel (id: %x) for "+
6✔
5300
                        "peer(%x)", pendingChanID[:], peerIDKey[:])
6✔
5301
        }
6✔
5302

5303
        // If the reservation was a PSBT funding flow and it was canceled by the
5304
        // remote peer, then we need to thread through a different error message
5305
        // to the subroutine that's waiting for the user input so it can return
5306
        // a nice error message to the user.
5307
        if ctx.reservation.IsPsbt() && byRemote {
5308
                ctx.reservation.RemoteCanceled()
26✔
5309
        }
26✔
5310

26✔
5311
        if err := ctx.reservation.Cancel(); err != nil {
26✔
5312
                return nil, fmt.Errorf("unable to cancel reservation: %w", err)
26✔
5313
        }
26✔
5314

26✔
5315
        delete(nodeReservations, pendingChanID)
26✔
5316

26✔
5317
        // If this was the last active reservation for this peer, delete the
26✔
5318
        // peer's entry altogether.
36✔
5319
        if len(nodeReservations) == 0 {
10✔
5320
                delete(f.activeReservations, peerIDKey)
10✔
5321
        }
10✔
5322
        return ctx, nil
10✔
5323
}
5324

19✔
5325
// deleteReservationCtx deletes the reservation uniquely identified by the
21✔
5326
// target public key of the peer, and the specified pending channel ID.
2✔
5327
func (f *Manager) deleteReservationCtx(peerKey *btcec.PublicKey,
2✔
5328
        pendingChanID PendingChanID) {
2✔
5329

5330
        peerIDKey := newSerializedKey(peerKey)
5331
        f.resMtx.Lock()
5332
        defer f.resMtx.Unlock()
5333

5334
        nodeReservations, ok := f.activeReservations[peerIDKey]
20✔
5335
        if !ok {
3✔
5336
                // No reservations for this node.
3✔
5337
                return
5338
        }
17✔
UNCOV
5339
        delete(nodeReservations, pendingChanID)
×
UNCOV
5340

×
5341
        // If this was the last active reservation for this peer, delete the
5342
        // peer's entry altogether.
17✔
5343
        if len(nodeReservations) == 0 {
17✔
5344
                delete(f.activeReservations, peerIDKey)
17✔
5345
        }
17✔
5346
}
34✔
5347

17✔
5348
// getReservationCtx returns the reservation context for a particular pending
17✔
5349
// channel ID for a target peer.
17✔
5350
func (f *Manager) getReservationCtx(peerKey *btcec.PublicKey,
5351
        pendingChanID PendingChanID) (*reservationWithCtx, error) {
5352

5353
        peerIDKey := newSerializedKey(peerKey)
5354
        f.resMtx.RLock()
5355
        resCtx, ok := f.activeReservations[peerIDKey][pendingChanID]
59✔
5356
        f.resMtx.RUnlock()
59✔
5357

59✔
5358
        if !ok {
59✔
5359
                return nil, fmt.Errorf("unknown channel (id: %x) for "+
59✔
5360
                        "peer(%x)", pendingChanID[:], peerIDKey[:])
59✔
5361
        }
59✔
5362

59✔
UNCOV
5363
        return resCtx, nil
×
UNCOV
5364
}
×
UNCOV
5365

×
5366
// IsPendingChannel returns a boolean indicating whether the channel identified
59✔
5367
// by the pendingChanID and given peer is pending, meaning it is in the process
59✔
5368
// of being funded. After the funding transaction has been confirmed, the
59✔
5369
// channel will receive a new, permanent channel ID, and will no longer be
59✔
5370
// considered pending.
111✔
5371
func (f *Manager) IsPendingChannel(pendingChanID PendingChanID,
52✔
5372
        peer lnpeer.Peer) bool {
52✔
5373

5374
        peerIDKey := newSerializedKey(peer.IdentityKey())
5375
        f.resMtx.RLock()
5376
        _, ok := f.activeReservations[peerIDKey][pendingChanID]
5377
        f.resMtx.RUnlock()
5378

94✔
5379
        return ok
94✔
5380
}
94✔
5381

94✔
5382
func copyPubKey(pub *btcec.PublicKey) *btcec.PublicKey {
94✔
5383
        var tmp btcec.JacobianPoint
94✔
5384
        pub.AsJacobian(&tmp)
94✔
5385
        tmp.ToAffine()
97✔
5386
        return btcec.NewPublicKey(&tmp.X, &tmp.Y)
3✔
5387
}
3✔
5388

3✔
5389
// defaultForwardingPolicy returns the default forwarding policy based on the
5390
// default routing policy and our local channel constraints.
94✔
5391
func (f *Manager) defaultForwardingPolicy(
5392
        bounds channeldb.ChannelStateBounds) *models.ForwardingPolicy {
5393

5394
        return &models.ForwardingPolicy{
5395
                MinHTLCOut:    bounds.MinHTLC,
5396
                MaxHTLC:       bounds.MaxPendingAmount,
5397
                BaseFee:       f.cfg.DefaultRoutingPolicy.BaseFee,
5398
                FeeRate:       f.cfg.DefaultRoutingPolicy.FeeRate,
5399
                TimeLockDelta: f.cfg.DefaultRoutingPolicy.TimeLockDelta,
3✔
5400
        }
3✔
5401
}
3✔
5402

3✔
5403
// saveInitialForwardingPolicy saves the forwarding policy for the provided
3✔
5404
// chanPoint in the channelOpeningStateBucket.
3✔
5405
func (f *Manager) saveInitialForwardingPolicy(chanID lnwire.ChannelID,
3✔
5406
        forwardingPolicy *models.ForwardingPolicy) error {
3✔
5407

3✔
5408
        return f.cfg.ChannelDB.SaveInitialForwardingPolicy(
5409
                chanID, forwardingPolicy,
388✔
5410
        )
388✔
5411
}
388✔
5412

388✔
5413
// getInitialForwardingPolicy fetches the initial forwarding policy for a given
388✔
5414
// channel id from the database which will be applied during the channel
388✔
5415
// announcement phase.
5416
func (f *Manager) getInitialForwardingPolicy(
5417
        chanID lnwire.ChannelID) (*models.ForwardingPolicy, error) {
5418

5419
        return f.cfg.ChannelDB.GetInitialForwardingPolicy(chanID)
107✔
5420
}
107✔
5421

107✔
5422
// deleteInitialForwardingPolicy removes channel fees for this chanID from
107✔
5423
// the database.
107✔
5424
func (f *Manager) deleteInitialForwardingPolicy(chanID lnwire.ChannelID) error {
107✔
5425
        return f.cfg.ChannelDB.DeleteInitialForwardingPolicy(chanID)
107✔
5426
}
107✔
5427

107✔
5428
// saveChannelOpeningState saves the channelOpeningState for the provided
107✔
5429
// chanPoint to the channelOpeningStateBucket.
5430
func (f *Manager) saveChannelOpeningState(chanPoint *wire.OutPoint,
5431
        state channelOpeningState, shortChanID *lnwire.ShortChannelID) error {
5432

5433
        var outpointBytes bytes.Buffer
72✔
5434
        if err := WriteOutpoint(&outpointBytes, chanPoint); err != nil {
72✔
5435
                return err
72✔
5436
        }
72✔
5437

72✔
5438
        // Save state and the uint64 representation of the shortChanID
72✔
5439
        // for later use.
5440
        scratch := make([]byte, 10)
5441
        byteOrder.PutUint16(scratch[:2], uint16(state))
5442
        byteOrder.PutUint64(scratch[2:], shortChanID.ToUint64())
5443

5444
        return f.cfg.ChannelDB.SaveChannelOpeningState(
97✔
5445
                outpointBytes.Bytes(), scratch,
97✔
5446
        )
97✔
5447
}
97✔
5448

5449
// getChannelOpeningState fetches the channelOpeningState for the provided
5450
// chanPoint from the database, or returns ErrChannelNotFound if the channel
5451
// is not found.
27✔
5452
func (f *Manager) getChannelOpeningState(chanPoint *wire.OutPoint) (
27✔
5453
        channelOpeningState, *lnwire.ShortChannelID, error) {
27✔
5454

5455
        var outpointBytes bytes.Buffer
5456
        if err := WriteOutpoint(&outpointBytes, chanPoint); err != nil {
5457
                return 0, nil, err
5458
        }
95✔
5459

95✔
5460
        value, err := f.cfg.ChannelDB.GetChannelOpeningState(
95✔
5461
                outpointBytes.Bytes(),
95✔
UNCOV
5462
        )
×
UNCOV
5463
        if err != nil {
×
5464
                return 0, nil, err
5465
        }
5466

5467
        state := channelOpeningState(byteOrder.Uint16(value[:2]))
95✔
5468
        shortChanID := lnwire.NewShortChanIDFromInt(byteOrder.Uint64(value[2:]))
95✔
5469
        return state, &shortChanID, nil
95✔
5470
}
95✔
5471

95✔
5472
// deleteChannelOpeningState removes any state for chanPoint from the database.
95✔
5473
func (f *Manager) deleteChannelOpeningState(chanPoint *wire.OutPoint) error {
95✔
5474
        var outpointBytes bytes.Buffer
5475
        if err := WriteOutpoint(&outpointBytes, chanPoint); err != nil {
5476
                return err
5477
        }
5478

5479
        return f.cfg.ChannelDB.DeleteChannelOpeningState(
5480
                outpointBytes.Bytes(),
255✔
5481
        )
255✔
5482
}
255✔
5483

255✔
UNCOV
5484
// selectShutdownScript selects the shutdown script we should send to the peer.
×
UNCOV
5485
// If we can use taproot, then we prefer that, otherwise we'll use a p2wkh
×
5486
// script.
5487
func (f *Manager) selectShutdownScript(taprootOK bool,
255✔
5488
) (lnwire.DeliveryAddress, error) {
255✔
5489

255✔
5490
        addrType := lnwallet.WitnessPubKey
307✔
5491
        if taprootOK {
52✔
5492
                addrType = lnwallet.TaprootPubkey
52✔
5493
        }
5494

206✔
5495
        addr, err := f.cfg.Wallet.NewAddress(
206✔
5496
                addrType, false, lnwallet.DefaultAccountName,
206✔
5497
        )
5498
        if err != nil {
5499
                return nil, err
5500
        }
27✔
5501

27✔
5502
        return txscript.PayToAddrScript(addr)
27✔
UNCOV
5503
}
×
UNCOV
5504

×
5505
// waitForPeerOnline blocks until the peer specified by peerPubkey comes online
5506
// and then returns the online peer.
27✔
5507
func (f *Manager) waitForPeerOnline(peerPubkey *btcec.PublicKey) (lnpeer.Peer,
27✔
5508
        error) {
27✔
5509

5510
        peerChan := make(chan lnpeer.Peer, 1)
5511

5512
        var peerKey [33]byte
5513
        copy(peerKey[:], peerPubkey.SerializeCompressed())
5514

UNCOV
5515
        f.cfg.NotifyWhenOnline(peerKey, peerChan)
×
UNCOV
5516

×
UNCOV
5517
        var peer lnpeer.Peer
×
UNCOV
5518
        select {
×
UNCOV
5519
        case peer = <-peerChan:
×
UNCOV
5520
        case <-f.quit:
×
5521
                return peer, ErrFundingManagerShuttingDown
UNCOV
5522
        }
×
UNCOV
5523
        return peer, nil
×
UNCOV
5524
}
×
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