package protofsm import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/fn/v2" "github.com/lightningnetwork/lnd/lnwire" ) // DaemonEvent is a special event that can be emitted by a state transition // function. A state machine can use this to perform side effects, such as // sending a message to a peer, or broadcasting a transaction. type DaemonEvent interface { daemonSealed() } // DaemonEventSet is a set of daemon events that can be emitted by a state // transition. type DaemonEventSet []DaemonEvent // DaemonEvents is a special type constraint that enumerates all the possible // types of daemon events. type DaemonEvents interface { SendMsgEvent[any] | BroadcastTxn | RegisterSpend[any] | RegisterConf[any] } // SendPredicate is a function that returns true if the target message should // sent. type SendPredicate = func() bool // SendMsgEvent is a special event that can be emitted by a state transition // that instructs the daemon to send the contained message to the target peer. type SendMsgEvent[Event any] struct { // TargetPeer is the peer to send the message to. TargetPeer btcec.PublicKey // Msgs is the set of messages to send to the target peer. Msgs []lnwire.Message // SendWhen implements a system for a conditional send once a special // send predicate has been met. // // TODO(roasbeef): contrast with usage of OnCommitFlush, etc SendWhen fn.Option[SendPredicate] // PostSendEvent is an optional event that is to be emitted after the // message has been sent. If a SendWhen is specified, then this will // only be executed after that returns true to unblock the send. PostSendEvent fn.Option[Event] } // daemonSealed indicates that this struct is a DaemonEvent instance. func (s *SendMsgEvent[E]) daemonSealed() {} // BroadcastTxn indicates the target transaction should be broadcast to the // network. type BroadcastTxn struct { // Tx is the transaction to broadcast. Tx *wire.MsgTx // Label is an optional label to attach to the transaction. Label string } // daemonSealed indicates that this struct is a DaemonEvent instance. func (b *BroadcastTxn) daemonSealed() {} // SpendMapper is a function that's used to map a spend notification to a // custom state machine event. type SpendMapper[Event any] func(*chainntnfs.SpendDetail) Event // RegisterSpend is used to request that a certain event is sent into the state // machine once the specified outpoint has been spent. type RegisterSpend[Event any] struct { // OutPoint is the outpoint on chain to watch. OutPoint wire.OutPoint // PkScript is the script that we expect to be spent along with the // outpoint. PkScript []byte // HeightHint is a value used to give the chain scanner a hint on how // far back it needs to start its search. HeightHint uint32 // PostSpendEvent is a special spend mapper, that if present, will be // used to map the protofsm spend event to a custom event. PostSpendEvent fn.Option[SpendMapper[Event]] } // daemonSealed indicates that this struct is a DaemonEvent instance. func (r *RegisterSpend[E]) daemonSealed() {} // RegisterConf is used to request that a certain event is sent into the state // machien once the specified outpoint has been spent. type RegisterConf[Event any] struct { // Txid is the txid of the txn we want to watch the chain for. Txid chainhash.Hash // PkScript is the script that we expect to be created along with the // outpoint. PkScript []byte // HeightHint is a value used to give the chain scanner a hint on how // far back it needs to start its search. HeightHint uint32 // NumConfs is the number of confirmations that the spending // transaction needs to dispatch an event. NumConfs fn.Option[uint32] // PostConfEvent is an event that's sent back to the requester once the // transaction specified above has confirmed in the chain with // sufficient depth. PostConfEvent fn.Option[Event] } // daemonSealed indicates that this struct is a DaemonEvent instance. func (r *RegisterConf[E]) daemonSealed() {}