Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 122 additions & 0 deletions protofsm/daemon_events.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
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"
"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() {}
29 changes: 29 additions & 0 deletions protofsm/log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package protofsm

import (
"github.com/btcsuite/btclog"
"github.com/lightningnetwork/lnd/build"
)

// log is a logger that is initialized with no output filters. This
// means the package will not perform any logging by default until the caller
// requests it.
var log btclog.Logger

// The default amount of logging is none.
func init() {
UseLogger(build.NewSubLogger("PFSM", nil))
}

// DisableLog disables all library log output. Logging output is disabled
// by default until UseLogger is called.
func DisableLog() {
UseLogger(btclog.Disabled)
}

// UseLogger uses a specified Logger to output package logging info.
// This should be used in preference to SetLogWriter if the caller is also
// using btclog.
func UseLogger(logger btclog.Logger) {
log = logger
}
15 changes: 15 additions & 0 deletions protofsm/msg_mapper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package protofsm

import (
"github.com/lightningnetwork/lnd/fn"
"github.com/lightningnetwork/lnd/lnwire"
)

// MsgMapper is used to map incoming wire messages into a FSM event. This is
// useful to decouple the translation of an outside or wire message into an
// event type that can be understood by the FSM.
type MsgMapper[Event any] interface {
// MapMsg maps a wire message into a FSM event. If the message is not
// mappable, then an None is returned.
MapMsg(msg lnwire.Message) fn.Option[Event]
}
Loading