Documentation
¶
Index ¶
- Variables
- func DisableLog()
- func ParseUpfrontShutdownAddress(address string, params *chaincfg.Params) (lnwire.DeliveryAddress, error)
- func UseLogger(logger btclog.Logger)
- type AsymmetricPeerState
- type AuxChanCloser
- type AuxCloseDesc
- type AuxCloseOutputs
- type AuxShutdownReq
- type ChanCloseCfg
- type ChanCloser
- func (c *ChanCloser) AuxOutputs() fn.Option[AuxCloseOutputs]
- func (c *ChanCloser) BeginNegotiation() (fn.Option[lnwire.ClosingSigned], error)
- func (c *ChanCloser) Channel() *lnwallet.LightningChannel
- func (c *ChanCloser) CloseRequest() *htlcswitch.ChanClose
- func (c *ChanCloser) ClosingTx() (*wire.MsgTx, error)
- func (c *ChanCloser) LocalCloseOutput() fn.Option[CloseOutput]
- func (c *ChanCloser) NegotiationHeight() uint32
- func (c *ChanCloser) ReceiveClosingSigned(msg lnwire.ClosingSigned) (fn.Option[lnwire.ClosingSigned], error)
- func (c *ChanCloser) ReceiveShutdown(msg lnwire.Shutdown) (fn.Option[lnwire.Shutdown], error)
- func (c *ChanCloser) RemoteCloseOutput() fn.Option[CloseOutput]
- func (c *ChanCloser) ShutdownChan() (*lnwire.Shutdown, error)
- type ChanStateObserver
- type Channel
- type ChannelActive
- type ChannelFlushed
- type ChannelFlushing
- type CloseChannelTerms
- func (c *CloseChannelTerms) DeriveCloseTxOuts() (*wire.TxOut, *wire.TxOut)
- func (c *CloseChannelTerms) LocalAmtIsDust() bool
- func (c *CloseChannelTerms) LocalCanPayFees(absoluteFee btcutil.Amount) bool
- func (c *CloseChannelTerms) RemoteAmtIsDust() bool
- func (c *CloseChannelTerms) RemoteCanPayFees(absoluteFee btcutil.Amount) bool
- type CloseErr
- type CloseFin
- type CloseOutput
- type ClosePending
- type CloseSigner
- type CloseStateTransition
- type ClosingNegotiation
- type CoopFeeEstimator
- type DeliveryAddrWithKey
- type Environment
- type ErrState
- type ErrStateCantPayForFee
- type LocalCloseStart
- type LocalOfferSent
- type LocalSigReceived
- type MusigSession
- type OfferReceivedEvent
- type ProtocolEvent
- type ProtocolEvents
- type ProtocolState
- type ProtocolStates
- type RbfChanCloser
- type RbfChanCloserCfg
- type RbfEvent
- type RbfMsgMapper
- type RbfMsgMapperT
- type RbfSpendMapper
- type RbfState
- type RbfStateSub
- type RemoteCloseStart
- type SendOfferEvent
- type SendShutdown
- type ShutdownBalances
- type ShutdownComplete
- type ShutdownPending
- type ShutdownReceived
- type ShutdownScripts
- type SimpleCoopFeeEstimator
- type SpendEvent
Constants ¶
This section is empty.
Variables ¶
var ( // ErrChanAlreadyClosing is returned when a channel shutdown is // attempted more than once. ErrChanAlreadyClosing = fmt.Errorf("channel shutdown already initiated") // ErrChanCloseNotFinished is returned when a caller attempts to access // a field or function that is contingent on the channel closure // negotiation already being completed. ErrChanCloseNotFinished = fmt.Errorf("close negotiation not finished") // ErrInvalidState is returned when the closing state machine receives a // message while it is in an unknown state. ErrInvalidState = fmt.Errorf("invalid state") // ErrUpfrontShutdownScriptMismatch is returned when a peer or end user // provides a cooperative close script which does not match the upfront // shutdown script previously set for that party. ErrUpfrontShutdownScriptMismatch = fmt.Errorf("shutdown script does not " + "match upfront shutdown script") // ErrProposalExceedsMaxFee is returned when as the initiator, the // latest fee proposal sent by the responder exceed our max fee. // responder. ErrProposalExceedsMaxFee = fmt.Errorf("latest fee proposal exceeds " + "max fee") // ErrInvalidShutdownScript is returned when we receive an address from // a peer that isn't either a p2wsh or p2tr address. ErrInvalidShutdownScript = fmt.Errorf("invalid shutdown script") )
var ( // ErrInvalidStateTransition is returned when we receive an unexpected // event for a given state. ErrInvalidStateTransition = fmt.Errorf("invalid state transition") // ErrTooManySigs is returned when we receive too many sigs from the // remote party in the ClosingSigs message. ErrTooManySigs = fmt.Errorf("too many sigs received") // ErrNoSig is returned when we receive no sig from the remote party. ErrNoSig = fmt.Errorf("no sig received") // ErrUnknownFinalBalance is returned if we're unable to determine the // final channel balance after a flush. ErrUnknownFinalBalance = fmt.Errorf("unknown final balance") // ErrRemoteCannotPay is returned if the remote party cannot pay the // pay for the fees when it sends a signature. ErrRemoteCannotPay = fmt.Errorf("remote cannot pay fees") // ErrNonFinalSequence is returned if we receive a non-final sequence // from the remote party for their signature. ErrNonFinalSequence = fmt.Errorf("received non-final sequence") // ErrCloserNoClosee is returned if our balance is dust, but the remote // party includes our output. ErrCloserNoClosee = fmt.Errorf("expected CloserNoClosee sig") // ErrCloserAndClosee is returned when we expect a sig covering both // outputs, it isn't present. ErrCloserAndClosee = fmt.Errorf("expected CloserAndClosee sig") // ErrWrongLocalScript is returned when the remote party sends a // ClosingComplete message that doesn't carry our last local script // sent. ErrWrongLocalScript = fmt.Errorf("wrong local script") )
var ( // ErrInvalidStateTransition is returned if the remote party tries to // close, but the thaw height hasn't been matched yet. ErrThawHeightNotReached = fmt.Errorf("thaw height not reached") )
Functions ¶
func ParseUpfrontShutdownAddress ¶
func ParseUpfrontShutdownAddress(address string, params *chaincfg.Params) (lnwire.DeliveryAddress, error)
ParseUpfrontShutdownAddress attempts to parse an upfront shutdown address. If the address is empty, it returns nil. If it successfully decoded the address, it returns a script that pays out to the address.
Types ¶
type AsymmetricPeerState ¶
type AsymmetricPeerState interface { ProtocolState // ShouldRouteTo returns true if the target state should process the // target event. ShouldRouteTo(ProtocolEvent) bool }
AsymmetricPeerState is an extension of the normal ProtocolState interface that gives a caller a hit on if the target state should process an incoming event or not.
type AuxChanCloser ¶
type AuxChanCloser interface { // ShutdownBlob returns the set of custom records that should be // included in the shutdown message. ShutdownBlob(req AuxShutdownReq) (fn.Option[lnwire.CustomRecords], error) // AuxCloseOutputs returns the set of custom outputs that should be used // to construct the co-op close transaction. AuxCloseOutputs(desc AuxCloseDesc) (fn.Option[AuxCloseOutputs], error) // FinalizeClose is called after the close transaction has been agreed // upon. FinalizeClose(desc AuxCloseDesc, closeTx *wire.MsgTx) error }
AuxChanCloser is used to allow an external caller to modify the co-op close transaction.
type AuxCloseDesc ¶
type AuxCloseDesc struct { AuxShutdownReq // CloseFee is the closing fee to be paid for this state. CloseFee btcutil.Amount // CommitFee is the fee that was paid for the last commitment. CommitFee btcutil.Amount // LocalCloseOutput is the output that the local node should be paid // to. This is None if the local party will not have an output on the // co-op close transaction. LocalCloseOutput fn.Option[CloseOutput] // RemoteCloseOutput is the output that the remote node should be paid // to. This will be None if the remote party will not have an output on // the co-op close transaction. RemoteCloseOutput fn.Option[CloseOutput] }
AuxCloseDesc is used to describe the channel close that is being performed.
type AuxCloseOutputs ¶
type AuxCloseOutputs struct { // ExtraCloseOutputs is a set of extra outputs that should be included // in the close transaction. ExtraCloseOutputs []lnwallet.CloseOutput // CustomSort is a custom function that can be used to sort the // transaction outputs. If this isn't set, then the default BIP-69 // sorting is used. CustomSort lnwallet.CloseSortFunc }
AuxCloseOutputs is used to specify extra outputs that should be used when constructing the co-op close transaction.
type AuxShutdownReq ¶
type AuxShutdownReq struct { // ChanPoint is the channel point of the channel that is being shut // down. ChanPoint wire.OutPoint // ShortChanID is the short channel ID of the channel that is being // closed. ShortChanID lnwire.ShortChannelID // Initiator is true if the local node is the initiator of the channel. Initiator bool // InternalKey is the internal key for the shutdown addr. This will // only be set for taproot shutdown addrs. InternalKey fn.Option[btcec.PublicKey] // CommitBlob is the blob that was included in the last commitment. CommitBlob fn.Option[tlv.Blob] // FundingBlob is the blob that was included in the funding state. FundingBlob fn.Option[tlv.Blob] }
AuxShutdownReq is used to request a set of extra custom records to include in the shutdown message.
type ChanCloseCfg ¶
type ChanCloseCfg struct { // Channel is the channel that should be closed. Channel Channel // MusigSession is used to handle generating musig2 nonces, and also // creating the proper set of closing options for taproot channels. MusigSession MusigSession // BroadcastTx broadcasts the passed transaction to the network. BroadcastTx func(*wire.MsgTx, string) error // DisableChannel disables a channel, resulting in it not being able to // forward payments. DisableChannel func(wire.OutPoint) error // Disconnect will disconnect from the remote peer in this close. Disconnect func() error // MaxFee, is non-zero represents the highest fee that the initiator is // willing to pay to close the channel. MaxFee chainfee.SatPerKWeight // ChainParams holds the parameters of the chain that we're active on. ChainParams *chaincfg.Params // Quit is a channel that should be sent upon in the occasion the state // machine should cease all progress and shutdown. Quit chan struct{} // FeeEstimator is used to estimate the absolute starting co-op close // fee. FeeEstimator CoopFeeEstimator // AuxCloser is an optional interface that can be used to modify the // way the co-op close process proceeds. AuxCloser fn.Option[AuxChanCloser] }
ChanCloseCfg holds all the items that a ChanCloser requires to carry out its duties.
type ChanCloser ¶
type ChanCloser struct {
// contains filtered or unexported fields
}
ChanCloser is a state machine that handles the cooperative channel closure procedure. This includes shutting down a channel, marking it ineligible for routing HTLC's, negotiating fees with the remote party, and finally broadcasting the fully signed closure transaction to the network.
func NewChanCloser ¶
func NewChanCloser(cfg ChanCloseCfg, deliveryScript DeliveryAddrWithKey, idealFeePerKw chainfee.SatPerKWeight, negotiationHeight uint32, closeReq *htlcswitch.ChanClose, closer lntypes.ChannelParty) *ChanCloser
NewChanCloser creates a new instance of the channel closure given the passed configuration, and delivery+fee preference. The final argument should only be populated iff, we're the initiator of this closing request.
func (*ChanCloser) AuxOutputs ¶
func (c *ChanCloser) AuxOutputs() fn.Option[AuxCloseOutputs]
AuxOutputs returns optional extra outputs.
func (*ChanCloser) BeginNegotiation ¶
func (c *ChanCloser) BeginNegotiation() (fn.Option[lnwire.ClosingSigned], error)
BeginNegotiation should be called when we have definitively reached a clean channel state and are ready to cooperatively arrive at a closing transaction. If it is our responsibility to kick off the negotiation, this method will generate a ClosingSigned message. If it is the remote's responsibility, then it will not. In either case it will transition the ChanCloser state machine to the negotiation phase wherein ClosingSigned messages are exchanged until a mutually agreeable result is achieved.
func (*ChanCloser) Channel ¶
func (c *ChanCloser) Channel() *lnwallet.LightningChannel
Channel returns the channel stored in the config as a *lnwallet.LightningChannel.
NOTE: This method will PANIC if the underlying channel implementation isn't the desired type.
func (*ChanCloser) CloseRequest ¶
func (c *ChanCloser) CloseRequest() *htlcswitch.ChanClose
CloseRequest returns the original close request that prompted the creation of the state machine.
NOTE: This will only return a non-nil pointer if we were the initiator of the cooperative closure workflow.
func (*ChanCloser) ClosingTx ¶
func (c *ChanCloser) ClosingTx() (*wire.MsgTx, error)
ClosingTx returns the fully signed, final closing transaction.
NOTE: This transaction is only available if the state machine is in the closeFinished state.
func (*ChanCloser) LocalCloseOutput ¶
func (c *ChanCloser) LocalCloseOutput() fn.Option[CloseOutput]
LocalCloseOutput returns the local close output.
func (*ChanCloser) NegotiationHeight ¶
func (c *ChanCloser) NegotiationHeight() uint32
NegotiationHeight returns the negotiation height.
func (*ChanCloser) ReceiveClosingSigned ¶
func (c *ChanCloser) ReceiveClosingSigned( msg lnwire.ClosingSigned) (fn.Option[lnwire.ClosingSigned], error)
ReceiveClosingSigned is a method that should be called whenever we receive a ClosingSigned message from the wire. It may or may not return a ClosingSigned of our own to send back to the remote.
func (*ChanCloser) ReceiveShutdown ¶
ReceiveShutdown takes a raw Shutdown message and uses it to try and advance the ChanCloser state machine, failing if it is coming in at an invalid time. If appropriate, it will also generate a Shutdown message of its own to send out to the peer. It is possible for this method to return None when no error occurred.
func (*ChanCloser) RemoteCloseOutput ¶
func (c *ChanCloser) RemoteCloseOutput() fn.Option[CloseOutput]
RemoteCloseOutput returns the remote close output.
func (*ChanCloser) ShutdownChan ¶
func (c *ChanCloser) ShutdownChan() (*lnwire.Shutdown, error)
ShutdownChan is the first method that's to be called by the initiator of the cooperative channel closure. This message returns the shutdown message to send to the remote party. Upon completion, we enter the closeShutdownInitiated phase as we await a response.
type ChanStateObserver ¶
type ChanStateObserver interface { // NoDanglingUpdates returns true if there are no dangling updates in // the channel. In other words, there are no active update messages // that haven't already been covered by a commit sig. NoDanglingUpdates() bool // DisableIncomingAdds instructs the channel link to disable process new // incoming add messages. DisableIncomingAdds() error // DisableOutgoingAdds instructs the channel link to disable process // new outgoing add messages. DisableOutgoingAdds() error // DisableChannel attempts to disable a channel (marking it ineligible // to forward), and also sends out a network update to disable the // channel. DisableChannel() error // MarkCoopBroadcasted persistently marks that the channel close // transaction has been broadcast. MarkCoopBroadcasted(*wire.MsgTx, bool) error // MarkShutdownSent persists the given ShutdownInfo. The existence of // the ShutdownInfo represents the fact that the Shutdown message has // been sent by us and so should be re-sent on re-establish. MarkShutdownSent(deliveryAddr []byte, isInitiator bool) error // FinalBalances is the balances of the channel once it has been // flushed. If Some, then this indicates that the channel is now in a // state where it's always flushed, so we can accelerate the state // transitions. FinalBalances() fn.Option[ShutdownBalances] }
ChanStateObserver is an interface used to observe state changes that occur in a channel. This can be used to figure out if we're able to send a shutdown message or not.
type Channel ¶
type Channel interface { // ChannelPoint returns the channel point of the target channel. ChannelPoint() wire.OutPoint // LocalCommitmentBlob may return the auxiliary data storage blob for // the local commitment transaction. LocalCommitmentBlob() fn.Option[tlv.Blob] // FundingBlob may return the auxiliary data storage blob related to // funding details for the channel. FundingBlob() fn.Option[tlv.Blob] // MarkCoopBroadcasted persistently marks that the channel close // transaction has been broadcast. MarkCoopBroadcasted(*wire.MsgTx, lntypes.ChannelParty) error // MarkShutdownSent persists the given ShutdownInfo. The existence of // the ShutdownInfo represents the fact that the Shutdown message has // been sent by us and so should be re-sent on re-establish. MarkShutdownSent(info *channeldb.ShutdownInfo) error // IsInitiator returns true we are the initiator of the channel. IsInitiator() bool // ShortChanID returns the scid of the channel. ShortChanID() lnwire.ShortChannelID // ChanType returns the channel type of the channel. ChanType() channeldb.ChannelType // FundingTxOut returns the funding output of the channel. FundingTxOut() *wire.TxOut // AbsoluteThawHeight returns the absolute thaw height of the channel. // If the channel is pending, or an unconfirmed zero conf channel, then // an error should be returned. AbsoluteThawHeight() (uint32, error) // LocalBalanceDust returns true if when creating a co-op close // transaction, the balance of the local party will be dust after // accounting for any anchor outputs. The dust value for the local // party is also returned. LocalBalanceDust() (bool, btcutil.Amount) // RemoteBalanceDust returns true if when creating a co-op close // transaction, the balance of the remote party will be dust after // accounting for any anchor outputs. The dust value the remote party // is also returned. RemoteBalanceDust() (bool, btcutil.Amount) // CommitBalances returns the local and remote balances in the current // commitment state. CommitBalances() (btcutil.Amount, btcutil.Amount) // CommitFee returns the commitment fee for the current commitment // state. CommitFee() btcutil.Amount // RemoteUpfrontShutdownScript returns the upfront shutdown script of // the remote party. If the remote party didn't specify such a script, // an empty delivery address should be returned. RemoteUpfrontShutdownScript() lnwire.DeliveryAddress // CreateCloseProposal creates a new co-op close proposal in the form // of a valid signature, the chainhash of the final txid, and our final // balance in the created state. CreateCloseProposal(proposedFee btcutil.Amount, localDeliveryScript []byte, remoteDeliveryScript []byte, closeOpt ...lnwallet.ChanCloseOpt, ) ( input.Signature, *wire.MsgTx, btcutil.Amount, error) // CompleteCooperativeClose persistently "completes" the cooperative // close by producing a fully signed co-op close transaction. CompleteCooperativeClose(localSig, remoteSig input.Signature, localDeliveryScript, remoteDeliveryScript []byte, proposedFee btcutil.Amount, closeOpt ...lnwallet.ChanCloseOpt, ) (*wire.MsgTx, btcutil.Amount, error) }
Channel abstracts away from the core channel state machine by exposing an interface that requires only the methods we need to carry out the channel closing process.
type ChannelActive ¶
type ChannelActive struct { }
ChannelActive is the base state for the channel closer state machine. In this state, we haven't begun the shutdown process yet, so the channel is still active. Receiving the ShutdownSent or ShutdownReceived events will transition us to the ChannelFushing state.
When we transition to this state, we emit a DaemonEvent to send the shutdown message if we received one ourselves. Alternatively, we may send out a new shutdown if we're initiating it for the very first time.
transition:
- fromState: None
- toState: ChannelFlushing
input events:
- SendShutdown
- ShutdownReceived
func (*ChannelActive) IsTerminal ¶
func (c *ChannelActive) IsTerminal() bool
IsTerminal returns true if the target state is a terminal state.
func (*ChannelActive) ProcessEvent ¶
func (c *ChannelActive) ProcessEvent(event ProtocolEvent, env *Environment, ) (*CloseStateTransition, error)
ProcessEvent takes a protocol event, and implements a state transition for the state. From this state, we can receive two possible incoming events: SendShutdown and ShutdownReceived. Both of these will transition us to the ChannelFlushing state.
func (*ChannelActive) String ¶
func (c *ChannelActive) String() string
String returns the name of the state for ChannelActive.
type ChannelFlushed ¶
type ChannelFlushed struct { // FreshFlush indicates if this is the first time the channel has been // flushed, or if this is a flush as part of an RBF iteration. FreshFlush bool // ShutdownBalances is the balances of the channel once it has been // flushed. We tie this to the ChannelFlushed state as this may not be // the same as the starting value. ShutdownBalances }
ChannelFlushed is an event that indicates the channel has been fully flushed can we can now start closing negotiation.
transition:
- fromState: ChannelFlushing
- toState: ClosingNegotiation
type ChannelFlushing ¶
type ChannelFlushing struct { // EarlyRemoteOffer is the offer we received from the remote party // before we obtained the local channel flushed event. We'll stash this // to process later. EarlyRemoteOffer fn.Option[OfferReceivedEvent] // ShutdownScripts store the set of scripts we'll use to initiate a coop // close. ShutdownScripts // IdealFeeRate is the ideal fee rate we'd like to use for the closing // transaction. Once the channel has been flushed, we'll use this as // our target fee rate. IdealFeeRate fn.Option[chainfee.SatPerVByte] }
ChannelFlushing is the state we enter into after we've received or sent a shutdown message. In this state, we wait the ChannelFlushed event, after which we'll transition to the CloseReady state.
transition:
- fromState: ShutdownPending
- toState: ClosingNegotiation
input events:
- ShutdownComplete
- ShutdownReceived
func (*ChannelFlushing) IsTerminal ¶
func (c *ChannelFlushing) IsTerminal() bool
IsTerminal returns true if the target state is a terminal state.
func (*ChannelFlushing) ProcessEvent ¶
func (c *ChannelFlushing) ProcessEvent(event ProtocolEvent, env *Environment, ) (*CloseStateTransition, error)
ProcessEvent takes a new protocol event, and figures out if we can transition to the next state, or just loop back upon ourself. If we receive a ShutdownReceived event, then we'll stay in the ChannelFlushing state, as we haven't yet fully cleared the channel. Otherwise, we can move to the CloseReady state which'll being the channel closing process.
func (*ChannelFlushing) String ¶
func (c *ChannelFlushing) String() string
String returns the name of the state for ChannelFlushing.
type CloseChannelTerms ¶
type CloseChannelTerms struct { ShutdownScripts ShutdownBalances }
CloseChannelTerms is a set of terms that we'll use to close the channel. This includes the balances of the channel, and the scripts we'll use to send each party's funds to.
func (*CloseChannelTerms) DeriveCloseTxOuts ¶
func (c *CloseChannelTerms) DeriveCloseTxOuts() (*wire.TxOut, *wire.TxOut)
DeriveCloseTxOuts takes the close terms, and returns the local and remote tx out for the close transaction. If an output is dust, then it'll be nil.
func (*CloseChannelTerms) LocalAmtIsDust ¶
func (c *CloseChannelTerms) LocalAmtIsDust() bool
LocalAmtIsDust returns true if the local output is dust.
func (*CloseChannelTerms) LocalCanPayFees ¶
func (c *CloseChannelTerms) LocalCanPayFees(absoluteFee btcutil.Amount) bool
LocalCanPayFees returns true if the local party can pay the absolute fee from their local settled balance.
func (*CloseChannelTerms) RemoteAmtIsDust ¶
func (c *CloseChannelTerms) RemoteAmtIsDust() bool
RemoteAmtIsDust returns true if the remote output is dust.
func (*CloseChannelTerms) RemoteCanPayFees ¶
func (c *CloseChannelTerms) RemoteCanPayFees(absoluteFee btcutil.Amount) bool
RemoteCanPayFees returns true if the remote party can pay the absolute fee from their remote settled balance.
type CloseErr ¶
type CloseErr struct { ErrState *CloseChannelTerms // Party indicates which party is at this state. This is used to // implement the state transition properly, based on ShouldRouteTo. Party lntypes.ChannelParty }
CloseErr is an error state in the protocol. We enter this state when a protocol constraint is violated, or an upfront sanity check fails.
func (*CloseErr) IsTerminal ¶
IsTerminal returns true if the target state is a terminal state.
func (*CloseErr) ProcessEvent ¶
func (c *CloseErr) ProcessEvent(event ProtocolEvent, env *Environment, ) (*CloseStateTransition, error)
ProcessEvent is a semi-terminal state in the rbf-coop close state machine. In this state, we hit a validation error in an earlier state, so we'll remain in this state for the user to examine. We may also process new requests to continue the state machine.
func (*CloseErr) ShouldRouteTo ¶
func (c *CloseErr) ShouldRouteTo(event ProtocolEvent) bool
ShouldRouteTo returns true if the target state should process the target event.
type CloseFin ¶
type CloseFin struct { // ConfirmedTx is the transaction that confirmed the channel close. ConfirmedTx *wire.MsgTx }
CloseFin is the terminal state for the channel closer state machine. At this point, the close tx has been confirmed on chain.
func (*CloseFin) IsTerminal ¶
IsTerminal returns true if the target state is a terminal state.
func (*CloseFin) ProcessEvent ¶
func (c *CloseFin) ProcessEvent(event ProtocolEvent, env *Environment, ) (*CloseStateTransition, error)
ProcessEvent is the event processing for out terminal state. In this state, we just keep looping back on ourselves.
type CloseOutput ¶
type CloseOutput struct { // Amt is the amount of the output. Amt btcutil.Amount // DustLimit is the dust limit for the local node. DustLimit btcutil.Amount // PkScript is the script that should be used to pay to the output. PkScript []byte // ShutdownRecords is the set of custom records that may result in // extra close outputs being added. ShutdownRecords lnwire.CustomRecords }
CloseOutput represents an output that should be included in the close transaction.
type ClosePending ¶
type ClosePending struct { // CloseTx is the pending close transaction. CloseTx *wire.MsgTx *CloseChannelTerms // FeeRate is the fee rate of the closing transaction. FeeRate chainfee.SatPerVByte // Party indicates which party is at this state. This is used to // implement the state transition properly, based on ShouldRouteTo. Party lntypes.ChannelParty }
ClosePending is the state we enter after concluding the negotiation for the remote or local state. At this point, given a confirmation notification we can terminate the process. Otherwise, we can receive a fresh CoopCloseReq to go back to the very start.
transition:
- fromState: LocalOfferSent || RemoteCloseStart
- toState: CloseFin
input events:
- LocalSigReceived
- OfferReceivedEvent
func (*ClosePending) IsTerminal ¶
func (c *ClosePending) IsTerminal() bool
IsTerminal returns true if the target state is a terminal state.
func (*ClosePending) ProcessEvent ¶
func (c *ClosePending) ProcessEvent(event ProtocolEvent, env *Environment, ) (*CloseStateTransition, error)
ProcessEvent is a semi-terminal state in the rbf-coop close state machine. In this state, we're waiting for either a confirmation, or for either side to attempt to create a new RBF'd co-op close transaction.
func (*ClosePending) ShouldRouteTo ¶
func (c *ClosePending) ShouldRouteTo(event ProtocolEvent) bool
ShouldRouteTo returns true if the target state should process the target event.
func (*ClosePending) String ¶
func (c *ClosePending) String() string
String returns the name of the state for ClosePending.
type CloseSigner ¶
type CloseSigner interface { // CreateCloseProposal creates a new co-op close proposal in the form // of a valid signature, the chainhash of the final txid, and our final // balance in the created state. CreateCloseProposal(proposedFee btcutil.Amount, localDeliveryScript []byte, remoteDeliveryScript []byte, closeOpt ...lnwallet.ChanCloseOpt, ) ( input.Signature, *wire.MsgTx, btcutil.Amount, error) // CompleteCooperativeClose persistently "completes" the cooperative // close by producing a fully signed co-op close transaction. CompleteCooperativeClose(localSig, remoteSig input.Signature, localDeliveryScript, remoteDeliveryScript []byte, proposedFee btcutil.Amount, closeOpt ...lnwallet.ChanCloseOpt, ) (*wire.MsgTx, btcutil.Amount, error) }
CloseSigner is an interface that abstracts away the details of the signing new coop close transactions.
type CloseStateTransition ¶
type CloseStateTransition = protofsm.StateTransition[ProtocolEvent, *Environment]
CloseStateTransition is the StateTransition type specific to the coop close state machine.
type ClosingNegotiation ¶
type ClosingNegotiation struct { // PeerStates is a composite state that contains the state for both the // local and remote parties. Our usage of Dual makes this a special // state that allows us to treat two states as a single state. We'll use // the ShouldRouteTo method to determine which state route incoming // events to. PeerState lntypes.Dual[AsymmetricPeerState] // CloseChannelTerms is the terms we'll use to close the channel. We // hold a value here which is pointed to by the various // AsymmetricPeerState instances. This allows us to update this value if // the remote peer sends a new address, with each of the state noting // the new value via a pointer. *CloseChannelTerms }
ClosingNegotiation is the state we transition to once the channel has been flushed. This is actually a composite state that contains one for each side of the channel, as the closing process is asymmetric. Once either of the peer states reaches the CloseFin state, then the channel is fully closed, and we'll transition to that terminal state.
transition:
- fromState: ChannelFlushing
- toState: CloseFin
input events:
- ChannelFlushed
func (*ClosingNegotiation) IsTerminal ¶
func (c *ClosingNegotiation) IsTerminal() bool
IsTerminal returns true if the target state is a terminal state.
func (*ClosingNegotiation) ProcessEvent ¶
func (c *ClosingNegotiation) ProcessEvent(event ProtocolEvent, env *Environment, ) (*CloseStateTransition, error)
ProcessEvent drives forward the composite states for the local and remote party in response to new events. From this state, we'll continue to drive forward the local and remote states until we arrive at the StateFin stage, or we loop back up to the ShutdownPending state.
func (*ClosingNegotiation) String ¶
func (c *ClosingNegotiation) String() string
String returns the name of the state for ClosingNegotiation.
type CoopFeeEstimator ¶
type CoopFeeEstimator interface { // EstimateFee estimates an _absolute_ fee for a co-op close transaction // given the local+remote tx outs (for the co-op close transaction), // channel type, and ideal fee rate. If a passed TxOut is nil, then // that indicates that an output is dust on the co-op close transaction // _before_ fees are accounted for. EstimateFee(chanType channeldb.ChannelType, localTxOut, remoteTxOut *wire.TxOut, idealFeeRate chainfee.SatPerKWeight) btcutil.Amount }
CoopFeeEstimator is used to estimate the fee of a co-op close transaction.
type DeliveryAddrWithKey ¶
type DeliveryAddrWithKey struct { // DeliveryAddress is the raw, serialized pkScript of the delivery // address. lnwire.DeliveryAddress // InternalKey is the Taproot internal key of the delivery address, if // the address is a P2TR output. InternalKey fn.Option[btcec.PublicKey] }
DeliveryAddrWithKey wraps a normal delivery addr, but also includes the internal key for the delivery addr if known.
type Environment ¶
type Environment struct { // ChainParams is the chain parameters for the channel. ChainParams chaincfg.Params // ChanPeer is the peer we're attempting to close the channel with. ChanPeer btcec.PublicKey // ChanPoint is the channel point of the active channel. ChanPoint wire.OutPoint // ChanID is the channel ID of the channel we're attempting to close. ChanID lnwire.ChannelID // ShortChanID is the short channel ID of the channel we're attempting // to close. Scid lnwire.ShortChannelID // ChanType is the type of channel we're attempting to close. ChanType channeldb.ChannelType // BlockHeight is the current block height. BlockHeight uint32 // DefaultFeeRate is the fee we'll use for the closing transaction if // the user didn't specify an ideal fee rate. This may happen if the // remote party is the one that initiates the co-op close. DefaultFeeRate chainfee.SatPerVByte // ThawHeight is the height at which the channel will be thawed. If // this is None, then co-op close can occur at any moment. ThawHeight fn.Option[uint32] // RemoteUprontShutdown is the upfront shutdown addr of the remote // party. We'll use this to validate if the remote peer is authorized to // close the channel with the sent addr or not. RemoteUpfrontShutdown fn.Option[lnwire.DeliveryAddress] // LocalUprontShutdown is our upfront shutdown address. If Some, then // we'll default to using this. LocalUpfrontShutdown fn.Option[lnwire.DeliveryAddress] // NewDeliveryScript is a function that returns a new delivery script. // This is used if we don't have an upfront shutdown addr, and no addr // was specified at closing time. NewDeliveryScript func() (lnwire.DeliveryAddress, error) // FeeEstimator is the fee estimator we'll use to determine the fee in // satoshis we'll pay given a local and/or remote output. FeeEstimator CoopFeeEstimator // ChanObserver is an interface used to observe state changes to the // channel. We'll use this to figure out when/if we can send certain // messages. ChanObserver ChanStateObserver // CloseSigner is the signer we'll use to sign the close transaction. // This is a part of the ChannelFlushed state, as the channel state // we'll be signing can only be determined once the channel has been // flushed. CloseSigner CloseSigner }
Environment is a set of dependencies that a state machine may need to carry out the logic for a given state transition. All fields are to be considered immutable, and will be fixed for the lifetime of the state machine.
func (*Environment) Name ¶
func (e *Environment) Name() string
Name returns the name of the environment. This is used to uniquely identify the environment of related state machines. For this state machine, the name is based on the channel ID.
type ErrState ¶
type ErrState interface { error // Err returns an error for the ErrState. Err() error // contains filtered or unexported methods }
ErrState can be used to introspect into a benign error related to a state transition.
type ErrStateCantPayForFee ¶
type ErrStateCantPayForFee struct {
// contains filtered or unexported fields
}
ErrStateCantPayForFee is sent when the local party attempts a fee update that they can't actually party for.
func NewErrStateCantPayForFee ¶
func NewErrStateCantPayForFee(localBalance, attemptedFee btcutil.Amount, ) *ErrStateCantPayForFee
NewErrStateCantPayForFee returns a new NewErrStateCantPayForFee error.
func (*ErrStateCantPayForFee) Err ¶
func (e *ErrStateCantPayForFee) Err() error
Err returns an error for the ErrState.
func (*ErrStateCantPayForFee) Error ¶
func (e *ErrStateCantPayForFee) Error() string
Error returns the error string for the ErrState.
func (*ErrStateCantPayForFee) String ¶
func (e *ErrStateCantPayForFee) String() string
String returns the string for the ErrStateCantPayForFee.
type LocalCloseStart ¶
type LocalCloseStart struct {
*CloseChannelTerms
}
LocalCloseStart is the state we enter into after we've received or sent shutdown, and the channel has been flushed. In this state, we'll emit a new event to send our offer to drive the rest of the process.
transition:
- fromState: ChannelFlushing
- toState: LocalOfferSent
input events:
- SendOfferEvent
func (*LocalCloseStart) IsTerminal ¶
func (l *LocalCloseStart) IsTerminal() bool
IsTerminal returns true if the target state is a terminal state.
func (*LocalCloseStart) ProcessEvent ¶
func (l *LocalCloseStart) ProcessEvent(event ProtocolEvent, env *Environment, ) (*CloseStateTransition, error)
ProcessEvent implements the event processing to kick off the process of obtaining a new (possibly RBF'd) signature for our commitment transaction.
func (*LocalCloseStart) ShouldRouteTo ¶
func (l *LocalCloseStart) ShouldRouteTo(event ProtocolEvent) bool
ShouldRouteTo returns true if the target state should process the target event.
func (*LocalCloseStart) String ¶
func (l *LocalCloseStart) String() string
String returns the name of the state for LocalCloseStart, including proposed fee details.
type LocalOfferSent ¶
type LocalOfferSent struct { *CloseChannelTerms // ProposedFee is the fee we proposed to the remote party. ProposedFee btcutil.Amount // ProposedFeeRate is the fee rate we proposed to the remote party. ProposedFeeRate chainfee.SatPerVByte // LocalSig is the signature we sent to the remote party. LocalSig lnwire.Sig }
LocalOfferSent is the state we transition to after we reveiver the SendOfferEvent in the LocalCloseStart state. With this state we send our offer to the remote party, then await a sig from them which concludes the local cooperative close process.
transition:
- fromState: LocalCloseStart
- toState: ClosePending
input events:
- LocalSigReceived
func (*LocalOfferSent) IsTerminal ¶
func (l *LocalOfferSent) IsTerminal() bool
IsTerminal returns true if the target state is a terminal state.
func (*LocalOfferSent) ProcessEvent ¶
func (l *LocalOfferSent) ProcessEvent(event ProtocolEvent, env *Environment, ) (*CloseStateTransition, error)
ProcessEvent implements the state transition function for the LocalOfferSent state. In this state, we'll wait for the remote party to send a close_signed message which gives us the ability to broadcast a new co-op close transaction.
func (*LocalOfferSent) ShouldRouteTo ¶
func (l *LocalOfferSent) ShouldRouteTo(event ProtocolEvent) bool
ShouldRouteTo returns true if the target state should process the target event.
func (*LocalOfferSent) String ¶
func (l *LocalOfferSent) String() string
String returns the name of the state for LocalOfferSent, including proposed.
type LocalSigReceived ¶
type LocalSigReceived struct { // SigMsg is the sig message we received from the remote party. SigMsg lnwire.ClosingSig }
LocalSigReceived is an event that indicates we've received a signature from the remote party, which signs our the co-op close transaction at our specified fee rate.
transition:
- fromState: LocalOfferSent
- toState: ClosePending
type MusigSession ¶
type MusigSession interface { // ProposalClosingOpts generates the set of closing options needed to // generate a new musig2 proposal signature. ProposalClosingOpts() ([]lnwallet.ChanCloseOpt, error) // CombineClosingOpts returns the options that should be used when // combining the final musig partial signature. The method also maps // the lnwire partial signatures into an input.Signature that can be // used more generally. CombineClosingOpts(localSig, remoteSig lnwire.PartialSig, ) (input.Signature, input.Signature, []lnwallet.ChanCloseOpt, error) // ClosingNonce generates the nonce we'll use to generate the musig2 // partial signatures for the co-op close transaction. ClosingNonce() (*musig2.Nonces, error) // InitRemoteNonce saves the remote nonce the party sent during their // shutdown message so it can be used later to generate and verify // signatures. InitRemoteNonce(nonce *musig2.Nonces) }
MusigSession is an interface that abstracts away the details of the musig2 session details. A session is used to generate the necessary closing options needed to close a channel cooperatively.
type OfferReceivedEvent ¶
type OfferReceivedEvent struct { // SigMsg is the signature message we received from the remote party. SigMsg lnwire.ClosingComplete }
OfferReceivedEvent is an event that indicates we've received an offer from the remote party. This applies to the RemoteCloseStart state.
transition:
- fromState: RemoteCloseStart
- toState: ClosePending
type ProtocolEvent ¶
type ProtocolEvent interface {
// contains filtered or unexported methods
}
ProtocolEvent is a special interface used to create the equivalent of a sum-type, but using a "sealed" interface. Protocol events can be used as input to trigger a state transition, and also as output to trigger a new set of events into the very same state machine.
func SpendMapper ¶
func SpendMapper(spendEvent *chainntnfs.SpendDetail) ProtocolEvent
type ProtocolEvents ¶
type ProtocolEvents interface { SendShutdown | ShutdownReceived | ShutdownComplete | ChannelFlushed | SendOfferEvent | OfferReceivedEvent | LocalSigReceived | SpendEvent }
ProtocolEvents is a special type constraint that enumerates all the possible protocol events. This is used mainly as type-level documentation, and may also be useful to constraint certain state transition functions.
type ProtocolState ¶
type ProtocolState interface { // IsTerminal returns true if the target state is a terminal state. IsTerminal() bool // ProcessEvent takes a protocol event, and implements a state // transition for the state. ProcessEvent(ProtocolEvent, *Environment) (*CloseStateTransition, error) // String returns the name of the state. String() string // contains filtered or unexported methods }
ProtocolState is our sum-type ish interface that represents the current protocol state.
type ProtocolStates ¶
type ProtocolStates interface { ChannelActive | ShutdownPending | ChannelFlushing | ClosingNegotiation | LocalCloseStart | LocalOfferSent | RemoteCloseStart | ClosePending | CloseFin | CloseErr }
ProtocolStates is a special type constraint that enumerates all the possible protocol states.
type RbfChanCloser ¶
type RbfChanCloser = protofsm.StateMachine[ProtocolEvent, *Environment]
RbfChanCloser is a state machine that handles the RBF-enabled cooperative channel close protocol.
type RbfChanCloserCfg ¶
type RbfChanCloserCfg = protofsm.StateMachineCfg[ProtocolEvent, *Environment]
RbfChanCloserCfg is a configuration struct that is used to initialize a new RBF chan closer state machine.
type RbfEvent ¶
type RbfEvent = protofsm.EmittedEvent[ProtocolEvent]
RbfEvent is a type alias for the event type of the RBF channel closer.
type RbfMsgMapper ¶
type RbfMsgMapper struct {
// contains filtered or unexported fields
}
RbfMsgMapper is a struct that implements the MsgMapper interface for the rbf-coop close state machine. This enables the state machine to be used with protofsm.
func NewRbfMsgMapper ¶
func NewRbfMsgMapper(blockHeight uint32, chanID lnwire.ChannelID, peerPub btcec.PublicKey) *RbfMsgMapper
NewRbfMsgMapper creates a new RbfMsgMapper instance given the current block height when the co-op close request was initiated.
func (*RbfMsgMapper) MapMsg ¶
func (r *RbfMsgMapper) MapMsg(wireMsg msgmux.PeerMsg) fn.Option[ProtocolEvent]
MapMsg maps a wire message into a FSM event. If the message is not mappable, then an error is returned.
type RbfMsgMapperT ¶
type RbfMsgMapperT = protofsm.MsgMapper[ProtocolEvent]
RbfMsgMapperT is a type used to map incoming wire messages to protocol events.
type RbfSpendMapper ¶
type RbfSpendMapper = protofsm.SpendMapper[ProtocolEvent]
RbfSpendMapper is a type used to map the generic spend event to one specific to this package.
type RbfState ¶
type RbfState = protofsm.State[ProtocolEvent, *Environment]
RbfState is a type alias for the state of the RBF channel closer.
type RbfStateSub ¶
type RbfStateSub = protofsm.StateSubscriber[ProtocolEvent, *Environment]
RbfStateSub is a type alias for the state subscription type of the RBF chan closer.
type RemoteCloseStart ¶
type RemoteCloseStart struct {
*CloseChannelTerms
}
RemoteCloseStart is similar to the LocalCloseStart, but is used to drive the process of signing an offer for the remote party
transition:
- fromState: ChannelFlushing
- toState: ClosePending
func (*RemoteCloseStart) IsTerminal ¶
func (l *RemoteCloseStart) IsTerminal() bool
IsTerminal returns true if the target state is a terminal state.
func (*RemoteCloseStart) ProcessEvent ¶
func (l *RemoteCloseStart) ProcessEvent(event ProtocolEvent, env *Environment, ) (*CloseStateTransition, error)
ProcessEvent implements the state transition function for the RemoteCloseStart. In this state, we'll wait for the remote party to send a closing_complete message. Assuming they can pay for the fees, we'll sign it ourselves, then transition to the next state of ClosePending.
func (*RemoteCloseStart) ShouldRouteTo ¶
func (l *RemoteCloseStart) ShouldRouteTo(event ProtocolEvent) bool
ShouldRouteTo returns true if the target state should process the target event.
func (*RemoteCloseStart) String ¶
func (r *RemoteCloseStart) String() string
String returns the name of the state for RemoteCloseStart.
type SendOfferEvent ¶
type SendOfferEvent struct { // TargetFeeRate is the fee rate we'll use for the closing transaction. TargetFeeRate chainfee.SatPerVByte }
SendOfferEvent is a self-triggered event that transitions us from the LocalCloseStart state to the LocalOfferSent state. This kicks off the new signing process for the co-op close process.
transition:
- fromState: LocalCloseStart
- toState: LocalOfferSent
type SendShutdown ¶
type SendShutdown struct { // DeliveryAddr is the address we'd like to receive the funds to. If // None, then a new addr will be generated. DeliveryAddr fn.Option[lnwire.DeliveryAddress] // IdealFeeRate is the ideal fee rate we'd like to use for the closing // attempt. IdealFeeRate chainfee.SatPerVByte }
SendShutdown indicates that the user wishes to co-op close the channel, so we should send a new shutdown message to the remote party.
transition:
- fromState: ChannelActive
- toState: ChannelFlushing
type ShutdownBalances ¶
type ShutdownBalances struct { // LocalBalance is the local balance of the channel. LocalBalance lnwire.MilliSatoshi // RemoteBalance is the remote balance of the channel. RemoteBalance lnwire.MilliSatoshi }
ShutdownBalances holds the local+remote balance once the channel has been fully flushed.
type ShutdownComplete ¶
type ShutdownComplete struct { }
ShutdownComplete is an event that indicates the channel has been fully shutdown. At this point, we'll go to the ChannelFlushing state so we can wait for all pending updates to be gone from the channel.
transition:
- fromState: ShutdownPending
- toState: ChannelFlushing
type ShutdownPending ¶
type ShutdownPending struct { // ShutdownScripts store the set of scripts we'll use to initiate a coop // close. ShutdownScripts // IdealFeeRate is the ideal fee rate we'd like to use for the closing // attempt. IdealFeeRate fn.Option[chainfee.SatPerVByte] // EarlyRemoteOffer is the offer we received from the remote party // before we received their shutdown message. We'll stash it to process // later. EarlyRemoteOffer fn.Option[OfferReceivedEvent] }
ShutdownPending is the state we enter into after we've sent or received the shutdown message. If we sent the shutdown, then we'll wait for the remote party to send a shutdown. Otherwise, if we received it, then we'll send our shutdown then go to the next state.
transition:
- fromState: ChannelActive
- toState: ChannelFlushing
input events:
- SendShutdown
- ShutdownReceived
func (*ShutdownPending) IsTerminal ¶
func (s *ShutdownPending) IsTerminal() bool
IsTerminal returns true if the target state is a terminal state.
func (*ShutdownPending) ProcessEvent ¶
func (s *ShutdownPending) ProcessEvent(event ProtocolEvent, env *Environment, ) (*CloseStateTransition, error)
ProcessEvent takes a protocol event, and implements a state transition for the state. Our path to this state will determine the set of valid events. If we were the one that sent the shutdown, then we'll just wait on the ShutdownReceived event. Otherwise, we received the shutdown, and can move forward once we receive the ShutdownComplete event. Receiving ShutdownComplete means that we've sent our shutdown, as this was specified as a post send event.
func (*ShutdownPending) String ¶
func (s *ShutdownPending) String() string
String returns the name of the state for ShutdownPending.
type ShutdownReceived ¶
type ShutdownReceived struct { // ShutdownScript is the script the remote party wants to use to // shutdown. ShutdownScript lnwire.DeliveryAddress // BlockHeight is the height at which the shutdown message was // received. This is used for channel leases to determine if a co-op // close can occur. BlockHeight uint32 }
ShutdownReceived indicates that we received a shutdown event so we need to enter the flushing state.
transition:
- fromState: ChannelActive
- toState: ChannelFlushing
type ShutdownScripts ¶
type ShutdownScripts struct { // LocalDeliveryScript is the script that we'll send our settled // channel funds to. LocalDeliveryScript lnwire.DeliveryAddress // RemoteDeliveryScript is the script that we'll send the remote // party's settled channel funds to. RemoteDeliveryScript lnwire.DeliveryAddress }
ShutdownScripts is a set of scripts that we'll use to co-op close the channel.
type SimpleCoopFeeEstimator ¶
type SimpleCoopFeeEstimator struct { }
SimpleCoopFeeEstimator is the default co-op close fee estimator. It assumes a normal segwit v0 channel, and that no outputs on the closing transaction are dust.
func (*SimpleCoopFeeEstimator) EstimateFee ¶
func (d *SimpleCoopFeeEstimator) EstimateFee(chanType channeldb.ChannelType, localTxOut, remoteTxOut *wire.TxOut, idealFeeRate chainfee.SatPerKWeight) btcutil.Amount
EstimateFee estimates an _absolute_ fee for a co-op close transaction given the local+remote tx outs (for the co-op close transaction), channel type, and ideal fee rate.
type SpendEvent ¶
type SpendEvent struct { // Tx is the spending transaction that has been confirmed. Tx *wire.MsgTx // BlockHeight is the height of the block that confirmed the // transaction. BlockHeight uint32 }
SpendEvent indicates that a transaction spending the funding outpoint has been confirmed in the main chain.