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

lightningnetwork / lnd / 13035292482

29 Jan 2025 03:59PM UTC coverage: 49.3% (-9.5%) from 58.777%
13035292482

Pull #9456

github

mohamedawnallah
docs: update release-notes-0.19.0.md

In this commit, we warn users about the removal
of RPCs `SendToRoute`, `SendToRouteSync`, `SendPayment`,
and `SendPaymentSync` in the next release 0.20.
Pull Request #9456: lnrpc+docs: deprecate warning `SendToRoute`, `SendToRouteSync`, `SendPayment`, and `SendPaymentSync` in Release 0.19

100634 of 204126 relevant lines covered (49.3%)

1.54 hits per line

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

0.0
/lnwallet/chancloser/rbf_coop_states.go
1
package chancloser
2

3
import (
4
        "fmt"
5

6
        "github.com/btcsuite/btcd/btcec/v2"
7
        "github.com/btcsuite/btcd/btcutil"
8
        "github.com/btcsuite/btcd/chaincfg"
9
        "github.com/btcsuite/btcd/wire"
10
        "github.com/lightningnetwork/lnd/chainntnfs"
11
        "github.com/lightningnetwork/lnd/channeldb"
12
        "github.com/lightningnetwork/lnd/fn/v2"
13
        "github.com/lightningnetwork/lnd/input"
14
        "github.com/lightningnetwork/lnd/lntypes"
15
        "github.com/lightningnetwork/lnd/lnwallet"
16
        "github.com/lightningnetwork/lnd/lnwallet/chainfee"
17
        "github.com/lightningnetwork/lnd/lnwire"
18
        "github.com/lightningnetwork/lnd/protofsm"
19
)
20

21
var (
22
        // ErrInvalidStateTransition is returned when we receive an unexpected
23
        // event for a given state.
24
        ErrInvalidStateTransition = fmt.Errorf("invalid state transition")
25

26
        // ErrTooManySigs is returned when we receive too many sigs from the
27
        // remote party in the ClosingSigs message.
28
        ErrTooManySigs = fmt.Errorf("too many sigs received")
29

30
        // ErrNoSig is returned when we receive no sig from the remote party.
31
        ErrNoSig = fmt.Errorf("no sig received")
32

33
        // ErrUnknownFinalBalance is returned if we're unable to determine the
34
        // final channel balance after a flush.
35
        ErrUnknownFinalBalance = fmt.Errorf("unknown final balance")
36

37
        // ErrRemoteCannotPay is returned if the remote party cannot pay the
38
        // pay for the fees when it sends a signature.
39
        ErrRemoteCannotPay = fmt.Errorf("remote cannot pay fees")
40

41
        // ErrNonFinalSequence is returned if we receive a non-final sequence
42
        // from the remote party for their signature.
43
        ErrNonFinalSequence = fmt.Errorf("received non-final sequence")
44

45
        // ErrCloserNoClosee is returned if our balance is dust, but the remote
46
        // party includes our output.
47
        ErrCloserNoClosee = fmt.Errorf("expected CloserNoClosee sig")
48

49
        // ErrCloserAndClosee is returned when we expect a sig covering both
50
        // outputs, it isn't present.
51
        ErrCloserAndClosee = fmt.Errorf("expected CloserAndClosee sig")
52
)
53

54
// ProtocolEvent is a special interface used to create the equivalent of a
55
// sum-type, but using a "sealed" interface. Protocol events can be used as
56
// input to trigger a state transition, and also as output to trigger a new set
57
// of events into the very same state machine.
58
type ProtocolEvent interface {
59
        protocolSealed()
60
}
61

62
// ProtocolEvents is a special type constraint that enumerates all the possible
63
// protocol events. This is used mainly as type-level documentation, and may
64
// also be useful to constraint certain state transition functions.
65
type ProtocolEvents interface {
66
        SendShutdown | ShutdownReceived | ShutdownComplete | ChannelFlushed |
67
                SendOfferEvent | OfferReceivedEvent | LocalSigReceived |
68
                SpendEvent
69
}
70

71
// SpendEvent indicates that a transaction spending the funding outpoint has
72
// been confirmed in the main chain.
73
type SpendEvent struct {
74
        // Tx is the spending transaction that has been confirmed.
75
        Tx *wire.MsgTx
76

77
        // BlockHeight is the height of the block that confirmed the
78
        // transaction.
79
        BlockHeight uint32
80
}
81

82
// protocolSealed indicates that this struct is a ProtocolEvent instance.
83
func (s *SpendEvent) protocolSealed() {}
×
84

85
// SendShutdown indicates that the user wishes to co-op close the channel, so we
86
// should send a new shutdown message to the remote party.
87
//
88
// transition:
89
//   - fromState: ChannelActive
90
//   - toState: ChannelFlushing
91
type SendShutdown struct {
92
        // DeliveryAddr is the address we'd like to receive the funds to. If
93
        // None, then a new addr will be generated.
94
        DeliveryAddr fn.Option[lnwire.DeliveryAddress]
95

96
        // IdealFeeRate is the ideal fee rate we'd like to use for the closing
97
        // attempt.
98
        IdealFeeRate chainfee.SatPerVByte
99
}
100

101
// protocolSealed indicates that this struct is a ProtocolEvent instance.
102
func (s *SendShutdown) protocolSealed() {}
×
103

104
// ShutdownReceived indicates that we received a shutdown event so we need to
105
// enter the flushing state.
106
//
107
// transition:
108
//   - fromState: ChannelActive
109
//   - toState: ChannelFlushing
110
type ShutdownReceived struct {
111
        // ShutdownScript is the script the remote party wants to use to
112
        // shutdown.
113
        ShutdownScript lnwire.DeliveryAddress
114

115
        // BlockHeight is the height at which the shutdown message was
116
        // received. This is used for channel leases to determine if a co-op
117
        // close can occur.
118
        BlockHeight uint32
119
}
120

121
// protocolSealed indicates that this struct is a ProtocolEvent instance.
122
func (s *ShutdownReceived) protocolSealed() {}
×
123

124
// ShutdownComplete is an event that indicates the channel has been fully
125
// shutdown. At this point, we'll go to the ChannelFlushing state so we can
126
// wait for all pending updates to be gone from the channel.
127
//
128
// transition:
129
//   - fromState: ShutdownPending
130
//   - toState: ChannelFlushing
131
type ShutdownComplete struct {
132
}
133

134
// protocolSealed indicates that this struct is a ProtocolEvent instance.
135
func (s *ShutdownComplete) protocolSealed() {}
×
136

137
// ShutdownBalances holds the local+remote balance once the channel has been
138
// fully flushed.
139
type ShutdownBalances struct {
140
        // LocalBalance is the local balance of the channel.
141
        LocalBalance lnwire.MilliSatoshi
142

143
        // RemoteBalance is the remote balance of the channel.
144
        RemoteBalance lnwire.MilliSatoshi
145
}
146

147
// unknownBalance is a special variable used to denote an unknown channel
148
// balance (channel not fully flushed yet).
149
var unknownBalance = ShutdownBalances{}
150

151
// ChannelFlushed is an event that indicates the channel has been fully flushed
152
// can we can now start closing negotiation.
153
//
154
// transition:
155
//   - fromState: ChannelFlushing
156
//   - toState: ClosingNegotiation
157
type ChannelFlushed struct {
158
        // FreshFlush indicates if this is the first time the channel has been
159
        // flushed, or if this is a flush as part of an RBF iteration.
160
        FreshFlush bool
161

162
        // ShutdownBalances is the balances of the channel once it has been
163
        // flushed. We tie this to the ChannelFlushed state as this may not be
164
        // the same as the starting value.
165
        ShutdownBalances
166
}
167

168
// protocolSealed indicates that this struct is a ProtocolEvent instance.
169
func (c *ChannelFlushed) protocolSealed() {}
×
170

171
// SendOfferEvent is a self-triggered event that transitions us from the
172
// LocalCloseStart state to the LocalOfferSent state. This kicks off the new
173
// signing process for the co-op close process.
174
//
175
// transition:
176
//   - fromState: LocalCloseStart
177
//   - toState: LocalOfferSent
178
type SendOfferEvent struct {
179
        // TargetFeeRate is the fee rate we'll use for the closing transaction.
180
        TargetFeeRate chainfee.SatPerVByte
181
}
182

183
// protocolSealed indicates that this struct is a ProtocolEvent instance.
184
func (s *SendOfferEvent) protocolSealed() {}
×
185

186
// LocalSigReceived is an event that indicates we've received a signature from
187
// the remote party, which signs our the co-op close transaction at our
188
// specified fee rate.
189
//
190
// transition:
191
//   - fromState: LocalOfferSent
192
//   - toState: ClosePending
193
type LocalSigReceived struct {
194
        // SigMsg is the sig message we received from the remote party.
195
        SigMsg lnwire.ClosingSig
196
}
197

198
// protocolSealed indicates that this struct is a ProtocolEvent instance.
199
func (s *LocalSigReceived) protocolSealed() {}
×
200

201
// OfferReceivedEvent is an event that indicates we've received an offer from
202
// the remote party. This applies to the RemoteCloseStart state.
203
//
204
// transition:
205
//   - fromState: RemoteCloseStart
206
//   - toState: ClosePending
207
type OfferReceivedEvent struct {
208
        // SigMsg is the signature message we received from the remote party.
209
        SigMsg lnwire.ClosingComplete
210
}
211

212
// protocolSealed indicates that this struct is a ProtocolEvent instance.
213
func (s *OfferReceivedEvent) protocolSealed() {}
×
214

215
// CloseSigner is an interface that abstracts away the details of the signing
216
// new coop close transactions.
217
type CloseSigner interface {
218
        // CreateCloseProposal creates a new co-op close proposal in the form
219
        // of a valid signature, the chainhash of the final txid, and our final
220
        // balance in the created state.
221
        CreateCloseProposal(proposedFee btcutil.Amount,
222
                localDeliveryScript []byte, remoteDeliveryScript []byte,
223
                closeOpt ...lnwallet.ChanCloseOpt,
224
        ) (
225
                input.Signature, *wire.MsgTx, btcutil.Amount, error)
226

227
        // CompleteCooperativeClose persistently "completes" the cooperative
228
        // close by producing a fully signed co-op close transaction.
229
        CompleteCooperativeClose(localSig, remoteSig input.Signature,
230
                localDeliveryScript, remoteDeliveryScript []byte,
231
                proposedFee btcutil.Amount, closeOpt ...lnwallet.ChanCloseOpt,
232
        ) (*wire.MsgTx, btcutil.Amount, error)
233
}
234

235
// ChanStateObserver is an interface used to observe state changes that occur
236
// in a channel. This can be used to figure out if we're able to send a
237
// shutdown message or not.
238
type ChanStateObserver interface {
239
        // NoDanglingUpdates returns true if there are no dangling updates in
240
        // the channel. In other words, there are no active update messages
241
        // that haven't already been covered by a commit sig.
242
        NoDanglingUpdates() bool
243

244
        // DisableIncomingAdds instructs the channel link to disable process new
245
        // incoming add messages.
246
        DisableIncomingAdds() error
247

248
        // DisableOutgoingAdds instructs the channel link to disable process
249
        // new outgoing add messages.
250
        DisableOutgoingAdds() error
251

252
        // DisableChannel attempts to disable a channel (marking it ineligible
253
        // to forward), and also sends out a network update to disable the
254
        // channel.
255
        DisableChannel() error
256

257
        // MarkCoopBroadcasted persistently marks that the channel close
258
        // transaction has been broadcast.
259
        MarkCoopBroadcasted(*wire.MsgTx, bool) error
260

261
        // MarkShutdownSent persists the given ShutdownInfo. The existence of
262
        // the ShutdownInfo represents the fact that the Shutdown message has
263
        // been sent by us and so should be re-sent on re-establish.
264
        MarkShutdownSent(deliveryAddr []byte, isInitiator bool) error
265

266
        // FinalBalances is the balances of the channel once it has been
267
        // flushed. If Some, then this indicates that the channel is now in a
268
        // state where it's always flushed, so we can accelerate the state
269
        // transitions.
270
        FinalBalances() fn.Option[ShutdownBalances]
271
}
272

273
// Environment is a set of dependencies that a state machine may need to carry
274
// out the logic for a given state transition. All fields are to be considered
275
// immutable, and will be fixed for the lifetime of the state machine.
276
type Environment struct {
277
        // ChainParams is the chain parameters for the channel.
278
        ChainParams chaincfg.Params
279

280
        // ChanPeer is the peer we're attempting to close the channel with.
281
        ChanPeer btcec.PublicKey
282

283
        // ChanPoint is the channel point of the active channel.
284
        ChanPoint wire.OutPoint
285

286
        // ChanID is the channel ID of the channel we're attempting to close.
287
        ChanID lnwire.ChannelID
288

289
        // ShortChanID is the short channel ID of the channel we're attempting
290
        // to close.
291
        Scid lnwire.ShortChannelID
292

293
        // ChanType is the type of channel we're attempting to close.
294
        ChanType channeldb.ChannelType
295

296
        // BlockHeight is the current block height.
297
        BlockHeight uint32
298

299
        // DefaultFeeRate is the fee we'll use for the closing transaction if
300
        // the user didn't specify an ideal fee rate. This may happen if the
301
        // remote party is the one that initiates the co-op close.
302
        DefaultFeeRate chainfee.SatPerVByte
303

304
        // ThawHeight is the height at which the channel will be thawed. If
305
        // this is None, then co-op close can occur at any moment.
306
        ThawHeight fn.Option[uint32]
307

308
        // RemoteUprontShutdown is the upfront shutdown addr of the remote
309
        // party. We'll use this to validate if the remote peer is authorized to
310
        // close the channel with the sent addr or not.
311
        RemoteUpfrontShutdown fn.Option[lnwire.DeliveryAddress]
312

313
        // LocalUprontShutdown is our upfront shutdown address. If Some, then
314
        // we'll default to using this.
315
        LocalUpfrontShutdown fn.Option[lnwire.DeliveryAddress]
316

317
        // NewDeliveryScript is a function that returns a new delivery script.
318
        // This is used if we don't have an upfront shutdown addr, and no addr
319
        // was specified at closing time.
320
        NewDeliveryScript func() (lnwire.DeliveryAddress, error)
321

322
        // FeeEstimator is the fee estimator we'll use to determine the fee in
323
        // satoshis we'll pay given a local and/or remote output.
324
        FeeEstimator CoopFeeEstimator
325

326
        // ChanObserver is an interface used to observe state changes to the
327
        // channel. We'll use this to figure out when/if we can send certain
328
        // messages.
329
        ChanObserver ChanStateObserver
330

331
        // CloseSigner is the signer we'll use to sign the close transaction.
332
        // This is a part of the ChannelFlushed state, as the channel state
333
        // we'll be signing can only be determined once the channel has been
334
        // flushed.
335
        CloseSigner CloseSigner
336
}
337

338
// Name returns the name of the environment. This is used to uniquely identify
339
// the environment of related state machines. For this state machine, the name
340
// is based on the channel ID.
341
func (e *Environment) Name() string {
×
342
        return fmt.Sprintf("rbf_chan_closer(%v)", e.ChanPoint)
×
343
}
×
344

345
// CloseStateTransition is the StateTransition type specific to the coop close
346
// state machine.
347
//
348
//nolint:ll
349
type CloseStateTransition = protofsm.StateTransition[ProtocolEvent, *Environment]
350

351
// ProtocolState is our sum-type ish interface that represents the current
352
// protocol state.
353
type ProtocolState interface {
354
        // protocolStateSealed is a special method that is used to seal the
355
        // interface (only types in this package can implement it).
356
        protocolStateSealed()
357

358
        // IsTerminal returns true if the target state is a terminal state.
359
        IsTerminal() bool
360

361
        // ProcessEvent takes a protocol event, and implements a state
362
        // transition for the state.
363
        ProcessEvent(ProtocolEvent, *Environment) (*CloseStateTransition, error)
364
}
365

366
// AsymmetricPeerState is an extension of the normal ProtocolState interface
367
// that gives a caller a hit on if the target state should process an incoming
368
// event or not.
369
type AsymmetricPeerState interface {
370
        ProtocolState
371

372
        // ShouldRouteTo returns true if the target state should process the
373
        // target event.
374
        ShouldRouteTo(ProtocolEvent) bool
375
}
376

377
// ProtocolStates is a special type constraint that enumerates all the possible
378
// protocol states.
379
type ProtocolStates interface {
380
        ChannelActive | ShutdownPending | ChannelFlushing | ClosingNegotiation |
381
                LocalCloseStart | LocalOfferSent | RemoteCloseStart |
382
                ClosePending | CloseFin
383
}
384

385
// ChannelActive is the base state for the channel closer state machine. In
386
// this state, we haven't begun the shutdown process yet, so the channel is
387
// still active. Receiving the ShutdownSent or ShutdownReceived events will
388
// transition us to the ChannelFushing state.
389
//
390
// When we transition to this state, we emit a DaemonEvent to send the shutdown
391
// message if we received one ourselves. Alternatively, we may send out a new
392
// shutdown if we're initiating it for the very first time.
393
//
394
// transition:
395
//   - fromState: None
396
//   - toState: ChannelFlushing
397
//
398
// input events:
399
//   - SendShutdown
400
//   - ShutdownReceived
401
type ChannelActive struct {
402
}
403

404
// IsTerminal returns true if the target state is a terminal state.
405
func (c *ChannelActive) IsTerminal() bool {
×
406
        return false
×
407
}
×
408

409
// protocolSealed indicates that this struct is a ProtocolEvent instance.
410
func (c *ChannelActive) protocolStateSealed() {}
×
411

412
// ShutdownScripts is a set of scripts that we'll use to co-op close the
413
// channel.
414
type ShutdownScripts struct {
415
        // LocalDeliveryScript is the script that we'll send our settled
416
        // channel funds to.
417
        LocalDeliveryScript lnwire.DeliveryAddress
418

419
        // RemoteDeliveryScript is the script that we'll send the remote
420
        // party's settled channel funds to.
421
        RemoteDeliveryScript lnwire.DeliveryAddress
422
}
423

424
// ShutdownPending is the state we enter into after we've sent or received the
425
// shutdown message. If we sent the shutdown, then we'll wait for the remote
426
// party to send a shutdown. Otherwise, if we received it, then we'll send our
427
// shutdown then go to the next state.
428
//
429
// transition:
430
//   - fromState: ChannelActive
431
//   - toState: ChannelFlushing
432
//
433
// input events:
434
//   - SendShutdown
435
//   - ShutdownReceived
436
type ShutdownPending struct {
437
        // ShutdownScripts store the set of scripts we'll use to initiate a coop
438
        // close.
439
        ShutdownScripts
440

441
        // IdealFeeRate is the ideal fee rate we'd like to use for the closing
442
        // attempt.
443
        IdealFeeRate fn.Option[chainfee.SatPerVByte]
444
}
445

446
// IsTerminal returns true if the target state is a terminal state.
447
func (s *ShutdownPending) IsTerminal() bool {
×
448
        return false
×
449
}
×
450

451
// protocolStateSealed indicates that this struct is a ProtocolEvent instance.
452
func (s *ShutdownPending) protocolStateSealed() {}
×
453

454
// ChannelFlushing is the state we enter into after we've received or sent a
455
// shutdown message. In this state, we wait the ChannelFlushed event, after
456
// which we'll transition to the CloseReady state.
457
//
458
// transition:
459
//   - fromState: ShutdownPending
460
//   - toState: ClosingNegotiation
461
//
462
// input events:
463
//   - ShutdownComplete
464
//   - ShutdownReceived
465
type ChannelFlushing struct {
466
        // EarlyRemoteOffer is the offer we received from the remote party
467
        // before we obtained the local channel flushed event. We'll stash this
468
        // to process later.
469
        EarlyRemoteOffer fn.Option[OfferReceivedEvent]
470

471
        // ShutdownScripts store the set of scripts we'll use to initiate a coop
472
        // close.
473
        ShutdownScripts
474

475
        // IdealFeeRate is the ideal fee rate we'd like to use for the closing
476
        // transaction. Once the channel has been flushed, we'll use this as
477
        // our target fee rate.
478
        IdealFeeRate fn.Option[chainfee.SatPerVByte]
479
}
480

481
// protocolStateSealed indicates that this struct is a ProtocolEvent instance.
482
func (c *ChannelFlushing) protocolStateSealed() {}
×
483

484
// IsTerminal returns true if the target state is a terminal state.
485
func (c *ChannelFlushing) IsTerminal() bool {
×
486
        return false
×
487
}
×
488

489
// ClosingNegotiation is the state we transition to once the channel has been
490
// flushed. This is actually a composite state that contains one for each side
491
// of the channel, as the closing process is asymmetric. Once either of the
492
// peer states reaches the CloseFin state, then the channel is fully closed,
493
// and we'll transition to that terminal state.
494
//
495
// transition:
496
//   - fromState: ChannelFlushing
497
//   - toState: CloseFin
498
//
499
// input events:
500
//   - ChannelFlushed
501
type ClosingNegotiation struct {
502
        // PeerStates is a composite state that contains the state for both the
503
        // local and remote parties. Our usage of Dual makes this a special
504
        // state that allows us to treat two states as a single state. We'll use
505
        // the ShouldRouteTo method to determine which state route incoming
506
        // events to.
507
        PeerState lntypes.Dual[AsymmetricPeerState]
508
}
509

510
// IsTerminal returns true if the target state is a terminal state.
511
func (c *ClosingNegotiation) IsTerminal() bool {
×
512
        return false
×
513
}
×
514

515
// protocolSealed indicates that this struct is a ProtocolEvent instance.
516
func (c *ClosingNegotiation) protocolStateSealed() {}
×
517

518
// CloseChannelTerms is a set of terms that we'll use to close the channel. This
519
// includes the balances of the channel, and the scripts we'll use to send each
520
// party's funds to.
521
type CloseChannelTerms struct {
522
        ShutdownScripts
523

524
        ShutdownBalances
525
}
526

527
// DeriveCloseTxOuts takes the close terms, and returns the local and remote tx
528
// out for the close transaction. If an output is dust, then it'll be nil.
529
//
530
// TODO(roasbeef): add func for w/e heuristic to not manifest own output?
531
func (c *CloseChannelTerms) DeriveCloseTxOuts() (*wire.TxOut, *wire.TxOut) {
×
532
        //nolint:ll
×
533
        deriveTxOut := func(balance btcutil.Amount, pkScript []byte) *wire.TxOut {
×
534
                dustLimit := lnwallet.DustLimitForSize(len(pkScript))
×
535
                if balance >= dustLimit {
×
536
                        return &wire.TxOut{
×
537
                                PkScript: pkScript,
×
538
                                Value:    int64(balance),
×
539
                        }
×
540
                }
×
541

542
                return nil
×
543
        }
544

545
        localTxOut := deriveTxOut(
×
546
                c.LocalBalance.ToSatoshis(),
×
547
                c.LocalDeliveryScript,
×
548
        )
×
549
        remoteTxOut := deriveTxOut(
×
550
                c.RemoteBalance.ToSatoshis(),
×
551
                c.RemoteDeliveryScript,
×
552
        )
×
553

×
554
        return localTxOut, remoteTxOut
×
555
}
556

557
// RemoteAmtIsDust returns true if the remote output is dust.
558
func (c *CloseChannelTerms) RemoteAmtIsDust() bool {
×
559
        return c.RemoteBalance.ToSatoshis() < lnwallet.DustLimitForSize(
×
560
                len(c.RemoteDeliveryScript),
×
561
        )
×
562
}
×
563

564
// LocalAmtIsDust returns true if the local output is dust.
565
func (c *CloseChannelTerms) LocalAmtIsDust() bool {
×
566
        return c.LocalBalance.ToSatoshis() < lnwallet.DustLimitForSize(
×
567
                len(c.LocalDeliveryScript),
×
568
        )
×
569
}
×
570

571
// LocalCanPayFees returns true if the local party can pay the absolute fee
572
// from their local settled balance.
573
func (c *CloseChannelTerms) LocalCanPayFees(absoluteFee btcutil.Amount) bool {
×
574
        return c.LocalBalance.ToSatoshis() >= absoluteFee
×
575
}
×
576

577
// RemoteCanPayFees returns true if the remote party can pay the absolute fee
578
// from their remote settled balance.
579
func (c *CloseChannelTerms) RemoteCanPayFees(absoluteFee btcutil.Amount) bool {
×
580
        return c.RemoteBalance.ToSatoshis() >= absoluteFee
×
581
}
×
582

583
// LocalCloseStart is the state we enter into after we've received or sent
584
// shutdown, and the channel has been flushed. In this state, we'll emit a new
585
// event to send our offer to drive the rest of the process.
586
//
587
// transition:
588
//   - fromState: ChannelFlushing
589
//   - toState: LocalOfferSent
590
//
591
// input events:
592
//   - SendOfferEvent
593
type LocalCloseStart struct {
594
        CloseChannelTerms
595
}
596

597
// ShouldRouteTo returns true if the target state should process the target
598
// event.
599
func (l *LocalCloseStart) ShouldRouteTo(event ProtocolEvent) bool {
×
600
        switch event.(type) {
×
601
        case *SendOfferEvent:
×
602
                return true
×
603
        default:
×
604
                return false
×
605
        }
606
}
607

608
// IsTerminal returns true if the target state is a terminal state.
609
func (l *LocalCloseStart) IsTerminal() bool {
×
610
        return false
×
611
}
×
612

613
// protocolStateaSealed indicates that this struct is a ProtocolEvent instance.
614
func (l *LocalCloseStart) protocolStateSealed() {}
×
615

616
// LocalOfferSent is the state we transition to after we reveiver the
617
// SendOfferEvent in the LocalCloseStart state. With this state we send our
618
// offer to the remote party, then await a sig from them which concludes the
619
// local cooperative close process.
620
//
621
// transition:
622
//   - fromState: LocalCloseStart
623
//   - toState: ClosePending
624
//
625
// input events:
626
//   - LocalSigReceived
627
type LocalOfferSent struct {
628
        CloseChannelTerms
629

630
        // ProposedFee is the fee we proposed to the remote party.
631
        ProposedFee btcutil.Amount
632

633
        // LocalSig is the signature we sent to the remote party.
634
        LocalSig lnwire.Sig
635
}
636

637
// ShouldRouteTo returns true if the target state should process the target
638
// event.
639
func (l *LocalOfferSent) ShouldRouteTo(event ProtocolEvent) bool {
×
640
        switch event.(type) {
×
641
        case *LocalSigReceived:
×
642
                return true
×
643
        default:
×
644
                return false
×
645
        }
646
}
647

648
// protocolStateaSealed indicates that this struct is a ProtocolEvent instance.
649
func (l *LocalOfferSent) protocolStateSealed() {}
×
650

651
// IsTerminal returns true if the target state is a terminal state.
652
func (l *LocalOfferSent) IsTerminal() bool {
×
653
        return false
×
654
}
×
655

656
// ClosePending is the state we enter after concluding the negotiation for the
657
// remote or local state. At this point, given a confirmation notification we
658
// can terminate the process. Otherwise, we can receive a fresh CoopCloseReq to
659
// go back to the very start.
660
//
661
// transition:
662
//   - fromState: LocalOfferSent || RemoteCloseStart
663
//   - toState: CloseFin
664
//
665
// input events:
666
//   - LocalSigReceived
667
//   - OfferReceivedEvent
668
type ClosePending struct {
669
        // CloseTx is the pending close transaction.
670
        CloseTx *wire.MsgTx
671
}
672

673
// ShouldRouteTo returns true if the target state should process the target
674
// event.
675
func (c *ClosePending) ShouldRouteTo(event ProtocolEvent) bool {
×
676
        switch event.(type) {
×
677
        case *SpendEvent:
×
678
                return true
×
679
        default:
×
680
                return false
×
681
        }
682
}
683

684
// protocolStateSealed indicates that this struct is a ProtocolEvent instance.
685
func (c *ClosePending) protocolStateSealed() {}
×
686

687
// IsTerminal returns true if the target state is a terminal state.
688
func (c *ClosePending) IsTerminal() bool {
×
689
        return true
×
690
}
×
691

692
// CloseFin is the terminal state for the channel closer state machine. At this
693
// point, the close tx has been confirmed on chain.
694
type CloseFin struct {
695
        // ConfirmedTx is the transaction that confirmed the channel close.
696
        ConfirmedTx *wire.MsgTx
697
}
698

699
// protocolStateSealed indicates that this struct is a ProtocolEvent instance.
700
func (c *CloseFin) protocolStateSealed() {}
×
701

702
// IsTerminal returns true if the target state is a terminal state.
703
func (c *CloseFin) IsTerminal() bool {
×
704
        return true
×
705
}
×
706

707
// RemoteCloseStart is similar to the LocalCloseStart, but is used to drive the
708
// process of signing an offer for the remote party
709
//
710
// transition:
711
//   - fromState: ChannelFlushing
712
//   - toState: ClosePending
713
type RemoteCloseStart struct {
714
        CloseChannelTerms
715
}
716

717
// ShouldRouteTo returns true if the target state should process the target
718
// event.
719
func (l *RemoteCloseStart) ShouldRouteTo(event ProtocolEvent) bool {
×
720
        switch event.(type) {
×
721
        case *OfferReceivedEvent:
×
722
                return true
×
723
        default:
×
724
                return false
×
725
        }
726
}
727

728
// protocolStateSealed indicates that this struct is a ProtocolEvent instance.
729
func (l *RemoteCloseStart) protocolStateSealed() {}
×
730

731
// IsTerminal returns true if the target state is a terminal state.
732
func (l *RemoteCloseStart) IsTerminal() bool {
×
733
        return false
×
734
}
×
735

736
// RbfChanCloser is a state machine that handles the RBF-enabled cooperative
737
// channel close protocol.
738
type RbfChanCloser = protofsm.StateMachine[ProtocolEvent, *Environment]
739

740
// RbfChanCloserCfg is a configuration struct that is used to initialize a new
741
// RBF chan closer state machine.
742
type RbfChanCloserCfg = protofsm.StateMachineCfg[ProtocolEvent, *Environment]
743

744
// RbfSpendMapper is a type used to map the generic spend event to one specific
745
// to this package.
746
type RbfSpendMapper = protofsm.SpendMapper[ProtocolEvent]
747

748
func SpendMapper(spendEvent *chainntnfs.SpendDetail) ProtocolEvent {
×
749
        return &SpendEvent{
×
750
                Tx:          spendEvent.SpendingTx,
×
751
                BlockHeight: uint32(spendEvent.SpendingHeight),
×
752
        }
×
753
}
×
754

755
// RbfMsgMapperT is a type used to map incoming wire messages to protocol
756
// events.
757
type RbfMsgMapperT = protofsm.MsgMapper[ProtocolEvent]
758

759
// RbfState is a type alias for the state of the RBF channel closer.
760
type RbfState = protofsm.State[ProtocolEvent, *Environment]
761

762
// RbfEvent is a type alias for the event type of the RBF channel closer.
763
type RbfEvent = protofsm.EmittedEvent[ProtocolEvent]
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