protofsm

package
v0.20.1-beta.rc1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 17, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrStateMachineShutdown occurs when trying to feed an event to a
	// StateMachine that has been asked to Stop.
	ErrStateMachineShutdown = fmt.Errorf("StateMachine is shutting down")
)

Functions

func DisableLog

func DisableLog()

DisableLog disables all library log output. Logging output is disabled by default until UseLogger is called.

func UseLogger

func UseLogger(logger btclog.Logger)

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.

Types

type BroadcastTxn

type BroadcastTxn struct {
	// Tx is the transaction to broadcast.
	Tx *wire.MsgTx

	// Label is an optional label to attach to the transaction.
	Label string
}

BroadcastTxn indicates the target transaction should be broadcast to the network.

type ConfMapper

type ConfMapper[Event any] func(*chainntnfs.TxConfirmation) Event

ConfMapper is a function that's used to map a confirmation notification to a custom state machine event.

type DaemonAdapters

type DaemonAdapters interface {
	// SendMessages sends the target set of messages to the target peer.
	SendMessages(btcec.PublicKey, []lnwire.Message) error

	// BroadcastTransaction broadcasts a transaction with the target label.
	BroadcastTransaction(*wire.MsgTx, string) error

	// RegisterConfirmationsNtfn registers an intent to be notified once
	// txid reaches numConfs confirmations. We also pass in the pkScript as
	// the default light client instead needs to match on scripts created
	// in the block. If a nil txid is passed in, then not only should we
	// match on the script, but we should also dispatch once the
	// transaction containing the script reaches numConfs confirmations.
	// This can be useful in instances where we only know the script in
	// advance, but not the transaction containing it.
	//
	// TODO(roasbeef): could abstract further?
	RegisterConfirmationsNtfn(txid *chainhash.Hash, pkScript []byte,
		numConfs, heightHint uint32,
		opts ...chainntnfs.NotifierOption) (
		*chainntnfs.ConfirmationEvent, error)

	// RegisterSpendNtfn registers an intent to be notified once the target
	// outpoint is successfully spent within a transaction. The script that
	// the outpoint creates must also be specified. This allows this
	// interface to be implemented by BIP 158-like filtering.
	RegisterSpendNtfn(outpoint *wire.OutPoint, pkScript []byte,
		heightHint uint32) (*chainntnfs.SpendEvent, error)
}

DaemonAdapters is a set of methods that server as adapters to bridge the pure world of the FSM to the real world of the daemon. These will be used to do things like broadcast transactions, or send messages to peers.

type DaemonEvent

type DaemonEvent interface {
	// contains filtered or unexported methods
}

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 DaemonEventSet

type DaemonEventSet []DaemonEvent

DaemonEventSet is a set of daemon events that can be emitted by a state transition.

type DaemonEvents

type DaemonEvents interface {
	SendMsgEvent[any] | BroadcastTxn | RegisterSpend[any] |
		RegisterConf[any]
}

DaemonEvents is a special type constraint that enumerates all the possible types of daemon events.

type EmittedEvent

type EmittedEvent[Event any] struct {
	// InternalEvent is an optional internal event that is to be routed
	// back to the target state. This enables state to trigger one or many
	// state transitions without a new external event.
	InternalEvent []Event

	// ExternalEvent is an optional external event that is to be sent to
	// the daemon for dispatch. Usually, this is some form of I/O.
	ExternalEvents DaemonEventSet
}

EmittedEvent is a special type that can be emitted by a state transition. This can container internal events which are to be routed back to the state, or external events which are to be sent to the daemon.

type Environment

type Environment interface {
	// Name returns the name of the environment. This is used to uniquely
	// identify the environment of related state machines.
	Name() string
}

Environment is an abstract interface that represents the environment that the state machine will execute using. From the PoV of the main state machine executor, we just care about being able to clean up any resources that were allocated by the environment.

type ErrorReporter

type ErrorReporter interface {
	// ReportError is a method that's used to report an error that occurred
	// during state machine execution.
	ReportError(err error)
}

ErrorReporter is an interface that's used to report errors that occur during state machine execution.

type MsgMapper

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 msgmux.PeerMsg) fn.Option[Event]
}

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 RegisterConf

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]

	// FullBlock is a boolean that indicates whether we want the full block
	// in the returned response. This is useful if callers want to create an
	// SPV proof for the transaction post conf.
	FullBlock bool

	// PostConfMapper is a special conf mapper, that if present, will be
	// used to map the protofsm confirmation event to a custom event.
	PostConfMapper fn.Option[ConfMapper[Event]]
}

RegisterConf is used to request that a certain event is sent into the state machien once the specified outpoint has been spent.

type RegisterSpend

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]]
}

RegisterSpend is used to request that a certain event is sent into the state machine once the specified outpoint has been spent.

type SendMsgEvent

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]
}

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 SendPredicate

type SendPredicate = func() bool

SendPredicate is a function that returns true if the target message should sent.

type SpendMapper

type SpendMapper[Event any] func(*chainntnfs.SpendDetail) Event

SpendMapper is a function that's used to map a spend notification to a custom state machine event.

type State

type State[Event any, Env Environment] interface {
	// ProcessEvent takes an event and an environment, and returns a new
	// state transition. This will be iteratively called until either a
	// terminal state is reached, or no further internal events are
	// emitted.
	ProcessEvent(event Event, env Env) (*StateTransition[Event, Env], error)

	// IsTerminal returns true if this state is terminal, and false
	// otherwise.
	IsTerminal() bool

	// String returns a human readable string that represents the state.
	String() string
}

State defines an abstract state along, namely its state transition function that takes as input an event and an environment, and returns a state transition (next state, and set of events to emit). As state can also either be terminal, or not, a terminal event causes state execution to halt.

type StateMachine

type StateMachine[Event any, Env Environment] struct {
	// contains filtered or unexported fields
}

StateMachine represents an abstract FSM that is able to process new incoming events and drive a state machine to termination. This implementation uses type params to abstract over the types of events and environment. Events trigger new state transitions, that use the environment to perform some action.

TODO(roasbeef): terminal check, daemon event execution, init?

func NewStateMachine

func NewStateMachine[Event any, Env Environment](
	cfg StateMachineCfg[Event, Env]) StateMachine[Event, Env]

NewStateMachine creates a new state machine given a set of daemon adapters, an initial state, an environment, and an event to process as if emitted at the onset of the state machine. Such an event can be used to set up tracking state such as a txid confirmation event.

func (*StateMachine[Event, Env]) CanHandle

func (s *StateMachine[Event, Env]) CanHandle(msg msgmux.PeerMsg) bool

CanHandle returns true if the target message can be routed to the state machine.

func (*StateMachine[Event, Env]) CurrentState

func (s *StateMachine[Event, Env]) CurrentState() (State[Event, Env], error)

CurrentState returns the current state of the state machine.

func (*StateMachine[Event, Env]) IsRunning

func (s *StateMachine[Event, Env]) IsRunning() bool

IsRunning returns true if the state machine is currently running.

func (*StateMachine[Event, Env]) Name

func (s *StateMachine[Event, Env]) Name() string

Name returns the name of the state machine's environment.

func (*StateMachine[Event, Env]) RegisterStateEvents

func (s *StateMachine[Event, Env]) RegisterStateEvents() StateSubscriber[
	Event, Env]

RegisterStateEvents registers a new event listener that will be notified of new state transitions.

func (*StateMachine[Event, Env]) RemoveStateSub

func (s *StateMachine[Event, Env]) RemoveStateSub(sub StateSubscriber[
	Event, Env])

RemoveStateSub removes the target state subscriber from the set of active subscribers.

func (*StateMachine[Event, Env]) SendEvent

func (s *StateMachine[Event, Env]) SendEvent(ctx context.Context, event Event)

SendEvent sends a new event to the state machine.

TODO(roasbeef): bool if processed?

func (*StateMachine[Event, Env]) SendMessage

func (s *StateMachine[Event, Env]) SendMessage(ctx context.Context,
	msg msgmux.PeerMsg) bool

SendMessage attempts to send a wire message to the state machine. If the message can be mapped using the default message mapper, then true is returned indicating that the message was processed. Otherwise, false is returned.

func (*StateMachine[Event, Env]) Start

func (s *StateMachine[Event, Env]) Start(ctx context.Context)

Start starts the state machine. This will spawn a goroutine that will drive the state machine to completion.

func (*StateMachine[Event, Env]) Stop

func (s *StateMachine[Event, Env]) Stop()

Stop stops the state machine. This will block until the state machine has reached a stopping point.

type StateMachineCfg

type StateMachineCfg[Event any, Env Environment] struct {
	// ErrorReporter is used to report errors that occur during state
	// transitions.
	ErrorReporter ErrorReporter

	// Daemon is a set of adapters that will be used to bridge the FSM to
	// the daemon.
	Daemon DaemonAdapters

	// InitialState is the initial state of the state machine.
	InitialState State[Event, Env]

	// Env is the environment that the state machine will use to execute.
	Env Env

	// InitEvent is an optional event that will be sent to the state
	// machine as if it was emitted at the onset of the state machine. This
	// can be used to set up tracking state such as a txid confirmation
	// event.
	InitEvent fn.Option[DaemonEvent]

	// MsgMapper is an optional message mapper that can be used to map
	// normal wire messages into FSM events.
	MsgMapper fn.Option[MsgMapper[Event]]

	// CustomPollInterval is an optional custom poll interval that can be
	// used to set a quicker interval for tests.
	CustomPollInterval fn.Option[time.Duration]
}

StateMachineCfg is a configuration struct that's used to create a new state machine.

type StateSubscriber

type StateSubscriber[E any, F Environment] *fn.EventReceiver[State[E, F]]

StateSubscriber represents an active subscription to be notified of new state transitions.

type StateTransition

type StateTransition[Event any, Env Environment] struct {
	// NextState is the next state to transition to.
	NextState State[Event, Env]

	// NewEvents is the set of events to emit.
	NewEvents fn.Option[EmittedEvent[Event]]
}

StateTransition is a state transition type. It denotes the next state to go to, and also the set of events to emit.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL