htlcswitch

package
v0.17.1-beta Latest Latest
Warning

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

Go to latest
Published: Nov 13, 2023 License: MIT Imports: 57 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// DefaultMaxOutgoingCltvExpiry is the maximum outgoing time lock that
	// the node accepts for forwarded payments. The value is relative to the
	// current block height. The reason to have a maximum is to prevent
	// funds getting locked up unreasonably long. Otherwise, an attacker
	// willing to lock its own funds too, could force the funds of this node
	// to be locked up for an indefinite (max int32) number of blocks.
	//
	// The value 2016 corresponds to on average two weeks worth of blocks
	// and is based on the maximum number of hops (20), the default CLTV
	// delta (40), and some extra margin to account for the other lightning
	// implementations and past lnd versions which used to have a default
	// CLTV delta of 144.
	DefaultMaxOutgoingCltvExpiry = 2016

	// DefaultMinLinkFeeUpdateTimeout represents the minimum interval in
	// which a link should propose to update its commitment fee rate.
	DefaultMinLinkFeeUpdateTimeout = 10 * time.Minute

	// DefaultMaxLinkFeeUpdateTimeout represents the maximum interval in
	// which a link should propose to update its commitment fee rate.
	DefaultMaxLinkFeeUpdateTimeout = 60 * time.Minute

	// DefaultMaxLinkFeeAllocation is the highest allocation we'll allow
	// a channel's commitment fee to be of its balance. This only applies to
	// the initiator of the channel.
	DefaultMaxLinkFeeAllocation float64 = 0.5
)
View Source
const (
	// ErrInternalError indicates that something internal in the link
	// failed. In this case we will send a generic error to our peer.
	ErrInternalError errorCode = iota

	// ErrRemoteError indicates that our peer sent an error, prompting up
	// to fail the link.
	ErrRemoteError

	// ErrRemoteUnresponsive indicates that our peer took too long to
	// complete a commitment dance.
	ErrRemoteUnresponsive

	// ErrSyncError indicates that we failed synchronizing the state of the
	// channel with our peer.
	ErrSyncError

	// ErrInvalidUpdate indicates that the peer send us an invalid update.
	ErrInvalidUpdate

	// ErrInvalidCommitment indicates that the remote peer sent us an
	// invalid commitment signature.
	ErrInvalidCommitment

	// ErrInvalidRevocation indicates that the remote peer send us an
	// invalid revocation message.
	ErrInvalidRevocation

	// ErrRecoveryError the channel was unable to be resumed, we need the
	// remote party to force close the channel out on chain now as a
	// result.
	ErrRecoveryError

	// ErrCircuitError indicates a duplicate keystone error was hit in the
	// circuit map. This is non-fatal and will resolve itself (usually
	// within several minutes).
	ErrCircuitError
)
View Source
const (
	// DefaultFwdEventInterval is the duration between attempts to flush
	// pending forwarding events to disk.
	DefaultFwdEventInterval = 15 * time.Second

	// DefaultLogInterval is the duration between attempts to log statistics
	// about forwarding events.
	DefaultLogInterval = 10 * time.Second

	// DefaultAckInterval is the duration between attempts to ack any settle
	// fails in a forwarding package.
	DefaultAckInterval = 15 * time.Second

	// DefaultMailboxDeliveryTimeout is the duration after which Adds will
	// be cancelled if they could not get added to an outgoing commitment.
	DefaultMailboxDeliveryTimeout = time.Minute
)

Variables

View Source
var (
	// ErrCorruptedCircuitMap indicates that the on-disk bucketing structure
	// has altered since the circuit map instance was initialized.
	ErrCorruptedCircuitMap = errors.New("circuit map has been corrupted")

	// ErrCircuitNotInHashIndex indicates that a particular circuit did not
	// appear in the in-memory hash index.
	ErrCircuitNotInHashIndex = errors.New("payment circuit not found in " +
		"hash index")

	// ErrUnknownCircuit signals that circuit could not be removed from the
	// map because it was not found.
	ErrUnknownCircuit = errors.New("unknown payment circuit")

	// ErrCircuitClosing signals that an htlc has already closed this
	// circuit in-memory.
	ErrCircuitClosing = errors.New("circuit has already been closed")

	// ErrDuplicateCircuit signals that this circuit was previously
	// added.
	ErrDuplicateCircuit = errors.New("duplicate circuit add")

	// ErrUnknownKeystone signals that no circuit was found using the
	// outgoing circuit key.
	ErrUnknownKeystone = errors.New("unknown circuit keystone")

	// ErrDuplicateKeystone signals that this circuit was previously
	// assigned a keystone.
	ErrDuplicateKeystone = errors.New("cannot add duplicate keystone")
)
View Source
var (
	// ErrDecayedLogInit is used to indicate a decayed log failed to create
	// the proper bucketing structure on startup.
	ErrDecayedLogInit = errors.New("unable to initialize decayed log")

	// ErrDecayedLogCorrupted signals that the anticipated bucketing
	// structure has diverged since initialization.
	ErrDecayedLogCorrupted = errors.New("decayed log structure corrupted")
)
View Source
var (
	// ErrFwdNotExists is an error returned when the caller tries to resolve
	// a forward that doesn't exist anymore.
	ErrFwdNotExists = errors.New("forward does not exist")

	// ErrUnsupportedFailureCode when processing of an unsupported failure
	// code is attempted.
	ErrUnsupportedFailureCode = errors.New("unsupported failure code")
)
View Source
var (
	// ErrLinkShuttingDown signals that the link is shutting down.
	ErrLinkShuttingDown = errors.New("link shutting down")

	// ErrLinkFailedShutdown signals that a requested shutdown failed.
	ErrLinkFailedShutdown = errors.New("link failed to shutdown")
)
View Source
var (
	// ErrMailBoxShuttingDown is returned when the mailbox is interrupted by
	// a shutdown request.
	ErrMailBoxShuttingDown = errors.New("mailbox is shutting down")

	// ErrPacketAlreadyExists signals that an attempt to add a packet failed
	// because it already exists in the mailbox.
	ErrPacketAlreadyExists = errors.New("mailbox already has packet")
)
View Source
var (

	// ErrPaymentIDNotFound is an error returned if the given paymentID is
	// not found.
	ErrPaymentIDNotFound = errors.New("paymentID not found")

	// ErrPaymentIDAlreadyExists is returned if we try to write a pending
	// payment whose paymentID already exists.
	ErrPaymentIDAlreadyExists = errors.New("paymentID already exists")
)
View Source
var (
	// ErrChannelLinkNotFound is used when channel link hasn't been found.
	ErrChannelLinkNotFound = errors.New("channel link not found")

	// ErrDuplicateAdd signals that the ADD htlc was already forwarded
	// through the switch and is locked into another commitment txn.
	ErrDuplicateAdd = errors.New("duplicate add HTLC detected")

	// ErrUnknownErrorDecryptor signals that we were unable to locate the
	// error decryptor for this payment. This is likely due to restarting
	// the daemon.
	ErrUnknownErrorDecryptor = errors.New("unknown error decryptor")

	// ErrSwitchExiting signaled when the switch has received a shutdown
	// request.
	ErrSwitchExiting = errors.New("htlcswitch shutting down")

	// ErrNoLinksFound is an error returned when we attempt to retrieve the
	// active links in the switch for a specific destination.
	ErrNoLinksFound = errors.New("no channel links found")

	// ErrUnreadableFailureMessage is returned when the failure message
	// cannot be decrypted.
	ErrUnreadableFailureMessage = errors.New("unreadable failure message")

	// ErrLocalAddFailed signals that the ADD htlc for a local payment
	// failed to be processed.
	ErrLocalAddFailed = errors.New("local add HTLC failed")

	// DefaultDustThreshold is the default threshold after which we'll fail
	// payments if they are dust. This is currently set to 500m msats.
	DefaultDustThreshold = lnwire.MilliSatoshi(500_000_000)
)
View Source
var (

	// ErrSequencerCorrupted signals that the persistence engine was not
	// initialized, or has been corrupted since startup.
	ErrSequencerCorrupted = errors.New(
		"sequencer database has been corrupted")
)

Functions

func DisableLog

func DisableLog()

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

func ExpectedFee

ExpectedFee computes the expected fee for a given htlc amount. The value returned from this function is to be used as a sanity check when forwarding HTLC's to ensure that an incoming HTLC properly adheres to our propagated forwarding policy.

TODO(roasbeef): also add in current available channel bandwidth, inverse func

func NewBoltBackendCreator

func NewBoltBackendCreator(dbPath,
	dbFileName string) func(boltCfg *kvdb.BoltConfig) (kvdb.Backend, error)

NewBoltBackendCreator returns a function that creates a new bbolt backend for the decayed logs database.

func NewMockObfuscator

func NewMockObfuscator() hop.ErrorEncrypter

NewMockObfuscator initializes a dummy mockObfuscator used for testing.

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 ChanClose

type ChanClose struct {
	// CloseType is a variable which signals the type of channel closure the
	// peer should execute.
	CloseType contractcourt.ChannelCloseType

	// ChanPoint represent the id of the channel which should be closed.
	ChanPoint *wire.OutPoint

	// TargetFeePerKw is the ideal fee that was specified by the caller.
	// This value is only utilized if the closure type is CloseRegular.
	// This will be the starting offered fee when the fee negotiation
	// process for the cooperative closure transaction kicks off.
	TargetFeePerKw chainfee.SatPerKWeight

	// MaxFee is the highest fee the caller is willing to pay.
	//
	// NOTE: This field is only respected if the caller is the initiator of
	// the channel.
	MaxFee chainfee.SatPerKWeight

	// DeliveryScript is an optional delivery script to pay funds out to.
	DeliveryScript lnwire.DeliveryAddress

	// Updates is used by request creator to receive the notifications about
	// execution of the close channel request.
	Updates chan interface{}

	// Err is used by request creator to receive request execution error.
	Err chan error
}

ChanClose represents a request which close a particular channel specified by its id.

type ChannelLink interface {

	// Embed the ChannelUpdateHandler interface.
	ChannelUpdateHandler

	// IsUnadvertised returns true if the underlying channel is
	// unadvertised.
	IsUnadvertised() bool

	// ChannelPoint returns the channel outpoint for the channel link.
	ChannelPoint() *wire.OutPoint

	// ShortChanID returns the short channel ID for the channel link. The
	// short channel ID encodes the exact location in the main chain that
	// the original funding output can be found.
	ShortChanID() lnwire.ShortChannelID

	// UpdateShortChanID updates the short channel ID for a link. This may
	// be required in the event that a link is created before the short
	// chan ID for it is known, or a re-org occurs, and the funding
	// transaction changes location within the chain.
	UpdateShortChanID() (lnwire.ShortChannelID, error)

	// UpdateForwardingPolicy updates the forwarding policy for the target
	// ChannelLink. Once updated, the link will use the new forwarding
	// policy to govern if it an incoming HTLC should be forwarded or not.
	UpdateForwardingPolicy(models.ForwardingPolicy)

	// CheckHtlcForward should return a nil error if the passed HTLC details
	// satisfy the current forwarding policy fo the target link. Otherwise,
	// a LinkError with a valid protocol failure message should be returned
	// in order to signal to the source of the HTLC, the policy consistency
	// issue.
	CheckHtlcForward(payHash [32]byte, incomingAmt lnwire.MilliSatoshi,
		amtToForward lnwire.MilliSatoshi,
		incomingTimeout, outgoingTimeout uint32,
		heightNow uint32, scid lnwire.ShortChannelID) *LinkError

	// CheckHtlcTransit should return a nil error if the passed HTLC details
	// satisfy the current channel policy.  Otherwise, a LinkError with a
	// valid protocol failure message should be returned in order to signal
	// the violation. This call is intended to be used for locally initiated
	// payments for which there is no corresponding incoming htlc.
	CheckHtlcTransit(payHash [32]byte, amt lnwire.MilliSatoshi,
		timeout uint32, heightNow uint32) *LinkError

	// Stats return the statistics of channel link. Number of updates,
	// total sent/received milli-satoshis.
	Stats() (uint64, lnwire.MilliSatoshi, lnwire.MilliSatoshi)

	// Peer returns the representation of remote peer with which we have
	// the channel link opened.
	Peer() lnpeer.Peer

	// AttachMailBox delivers an active MailBox to the link. The MailBox may
	// have buffered messages.
	AttachMailBox(MailBox)

	// Start/Stop are used to initiate the start/stop of the channel link
	// functioning.
	Start() error
	Stop()
	// contains filtered or unexported methods
}

ChannelLink is an interface which represents the subsystem for managing the incoming htlc requests, applying the changes to the channel, and also propagating/forwarding it to htlc switch.

abstraction level
     ^
     |
     | - - - - - - - - - - - - Lightning - - - - - - - - - - - - -
     |
     | (Switch)		     (Switch)		       (Switch)
     |  Alice <-- channel link --> Bob <-- channel link --> Carol
     |
     | - - - - - - - - - - - - - TCP - - - - - - - - - - - - - - -
     |
     |  (Peer) 		     (Peer)	                (Peer)
     |  Alice <----- tcp conn --> Bob <---- tcp conn -----> Carol
     |
func NewChannelLink(cfg ChannelLinkConfig,
	channel *lnwallet.LightningChannel) ChannelLink

NewChannelLink creates a new instance of a ChannelLink given a configuration and active channel that will be used to verify/apply updates to.

type ChannelLinkConfig

type ChannelLinkConfig struct {
	// FwrdingPolicy is the initial forwarding policy to be used when
	// deciding whether to forwarding incoming HTLC's or not. This value
	// can be updated with subsequent calls to UpdateForwardingPolicy
	// targeted at a given ChannelLink concrete interface implementation.
	FwrdingPolicy models.ForwardingPolicy

	// Circuits provides restricted access to the switch's circuit map,
	// allowing the link to open and close circuits.
	Circuits CircuitModifier

	// Switch provides a reference to the HTLC switch, we only use this in
	// testing to access circuit operations not typically exposed by the
	// CircuitModifier.
	//
	// TODO(conner): remove after refactoring htlcswitch testing framework.
	Switch *Switch

	// BestHeight returns the best known height.
	BestHeight func() uint32

	// ForwardPackets attempts to forward the batch of htlcs through the
	// switch. The function returns and error in case it fails to send one or
	// more packets. The link's quit signal should be provided to allow
	// cancellation of forwarding during link shutdown.
	ForwardPackets func(chan struct{}, bool, ...*htlcPacket) error

	// DecodeHopIterators facilitates batched decoding of HTLC Sphinx onion
	// blobs, which are then used to inform how to forward an HTLC.
	//
	// NOTE: This function assumes the same set of readers and preimages
	// are always presented for the same identifier.
	DecodeHopIterators func([]byte, []hop.DecodeHopIteratorRequest) (
		[]hop.DecodeHopIteratorResponse, error)

	// ExtractErrorEncrypter function is responsible for decoding HTLC
	// Sphinx onion blob, and creating onion failure obfuscator.
	ExtractErrorEncrypter hop.ErrorEncrypterExtracter

	// FetchLastChannelUpdate retrieves the latest routing policy for a
	// target channel. This channel will typically be the outgoing channel
	// specified when we receive an incoming HTLC.  This will be used to
	// provide payment senders our latest policy when sending encrypted
	// error messages.
	FetchLastChannelUpdate func(lnwire.ShortChannelID) (*lnwire.ChannelUpdate, error)

	// Peer is a lightning network node with which we have the channel link
	// opened.
	Peer lnpeer.Peer

	// Registry is a sub-system which responsible for managing the invoices
	// in thread-safe manner.
	Registry InvoiceDatabase

	// PreimageCache is a global witness beacon that houses any new
	// preimages discovered by other links. We'll use this to add new
	// witnesses that we discover which will notify any sub-systems
	// subscribed to new events.
	PreimageCache contractcourt.WitnessBeacon

	// OnChannelFailure is a function closure that we'll call if the
	// channel failed for some reason. Depending on the severity of the
	// error, the closure potentially must force close this channel and
	// disconnect the peer.
	//
	// NOTE: The method must return in order for the ChannelLink to be able
	// to shut down properly.
	OnChannelFailure func(lnwire.ChannelID, lnwire.ShortChannelID,
		LinkFailureError)

	// UpdateContractSignals is a function closure that we'll use to update
	// outside sub-systems with this channel's latest ShortChannelID.
	UpdateContractSignals func(*contractcourt.ContractSignals) error

	// NotifyContractUpdate is a function closure that we'll use to update
	// the contractcourt and more specifically the ChannelArbitrator of the
	// latest channel state.
	NotifyContractUpdate func(*contractcourt.ContractUpdate) error

	// ChainEvents is an active subscription to the chain watcher for this
	// channel to be notified of any on-chain activity related to this
	// channel.
	ChainEvents *contractcourt.ChainEventSubscription

	// FeeEstimator is an instance of a live fee estimator which will be
	// used to dynamically regulate the current fee of the commitment
	// transaction to ensure timely confirmation.
	FeeEstimator chainfee.Estimator

	// hodl.Mask is a bitvector composed of hodl.Flags, specifying breakpoints
	// for HTLC forwarding internal to the switch.
	//
	// NOTE: This should only be used for testing.
	HodlMask hodl.Mask

	// SyncStates is used to indicate that we need send the channel
	// reestablishment message to the remote peer. It should be done if our
	// clients have been restarted, or remote peer have been reconnected.
	SyncStates bool

	// BatchTicker is the ticker that determines the interval that we'll
	// use to check the batch to see if there're any updates we should
	// flush out. By batching updates into a single commit, we attempt to
	// increase throughput by maximizing the number of updates coalesced
	// into a single commit.
	BatchTicker ticker.Ticker

	// FwdPkgGCTicker is the ticker determining the frequency at which
	// garbage collection of forwarding packages occurs. We use a
	// time-based approach, as opposed to block epochs, as to not hinder
	// syncing.
	FwdPkgGCTicker ticker.Ticker

	// PendingCommitTicker is a ticker that allows the link to determine if
	// a locally initiated commitment dance gets stuck waiting for the
	// remote party to revoke.
	PendingCommitTicker ticker.Ticker

	// BatchSize is the max size of a batch of updates done to the link
	// before we do a state update.
	BatchSize uint32

	// UnsafeReplay will cause a link to replay the adds in its latest
	// commitment txn after the link is restarted. This should only be used
	// in testing, it is here to ensure the sphinx replay detection on the
	// receiving node is persistent.
	UnsafeReplay bool

	// MinFeeUpdateTimeout represents the minimum interval in which a link
	// will propose to update its commitment fee rate. A random timeout will
	// be selected between this and MaxFeeUpdateTimeout.
	MinFeeUpdateTimeout time.Duration

	// MaxFeeUpdateTimeout represents the maximum interval in which a link
	// will propose to update its commitment fee rate. A random timeout will
	// be selected between this and MinFeeUpdateTimeout.
	MaxFeeUpdateTimeout time.Duration

	// OutgoingCltvRejectDelta defines the number of blocks before expiry of
	// an htlc where we don't offer an htlc anymore. This should be at least
	// the outgoing broadcast delta, because in any case we don't want to
	// risk offering an htlc that triggers channel closure.
	OutgoingCltvRejectDelta uint32

	// TowerClient is an optional engine that manages the signing,
	// encrypting, and uploading of justice transactions to the daemon's
	// configured set of watchtowers for legacy channels.
	TowerClient TowerClient

	// MaxOutgoingCltvExpiry is the maximum outgoing timelock that the link
	// should accept for a forwarded HTLC. The value is relative to the
	// current block height.
	MaxOutgoingCltvExpiry uint32

	// MaxFeeAllocation is the highest allocation we'll allow a channel's
	// commitment fee to be of its balance. This only applies to the
	// initiator of the channel.
	MaxFeeAllocation float64

	// MaxAnchorsCommitFeeRate is the max commitment fee rate we'll use as
	// the initiator for channels of the anchor type.
	MaxAnchorsCommitFeeRate chainfee.SatPerKWeight

	// NotifyActiveLink allows the link to tell the ChannelNotifier when a
	// link is first started.
	NotifyActiveLink func(wire.OutPoint)

	// NotifyActiveChannel allows the link to tell the ChannelNotifier when
	// channels becomes active.
	NotifyActiveChannel func(wire.OutPoint)

	// NotifyInactiveChannel allows the switch to tell the ChannelNotifier
	// when channels become inactive.
	NotifyInactiveChannel func(wire.OutPoint)

	// NotifyInactiveLinkEvent allows the switch to tell the
	// ChannelNotifier when a channel link become inactive.
	NotifyInactiveLinkEvent func(wire.OutPoint)

	// HtlcNotifier is an instance of a htlcNotifier which we will pipe htlc
	// events through.
	HtlcNotifier htlcNotifier

	// FailAliasUpdate is a function used to fail an HTLC for an
	// option_scid_alias channel.
	FailAliasUpdate func(sid lnwire.ShortChannelID,
		incoming bool) *lnwire.ChannelUpdate

	// GetAliases is used by the link and switch to fetch the set of
	// aliases for a given link.
	GetAliases func(base lnwire.ShortChannelID) []lnwire.ShortChannelID
}

ChannelLinkConfig defines the configuration for the channel link. ALL elements within the configuration MUST be non-nil for channel link to carry out its duties.

type ChannelUpdateHandler

type ChannelUpdateHandler interface {
	// HandleChannelUpdate handles the htlc requests as settle/add/fail
	// which sent to us from remote peer we have a channel with.
	//
	// NOTE: This function MUST be non-blocking (or block as little as
	// possible).
	HandleChannelUpdate(lnwire.Message)

	// ChanID returns the channel ID for the channel link. The channel ID
	// is a more compact representation of a channel's full outpoint.
	ChanID() lnwire.ChannelID

	// Bandwidth returns the amount of milli-satoshis which current link
	// might pass through channel link. The value returned from this method
	// represents the up to date available flow through the channel. This
	// takes into account any forwarded but un-cleared HTLC's, and any
	// HTLC's which have been set to the over flow queue.
	Bandwidth() lnwire.MilliSatoshi

	// EligibleToForward returns a bool indicating if the channel is able
	// to actively accept requests to forward HTLC's. A channel may be
	// active, but not able to forward HTLC's if it hasn't yet finalized
	// the pre-channel operation protocol with the remote peer. The switch
	// will use this function in forwarding decisions accordingly.
	EligibleToForward() bool

	// MayAddOutgoingHtlc returns an error if we may not add an outgoing
	// htlc to the channel, taking the amount of the htlc to add as a
	// parameter.
	MayAddOutgoingHtlc(lnwire.MilliSatoshi) error

	// ShutdownIfChannelClean shuts the link down if the channel state is
	// clean. This can be used with dynamic commitment negotiation or coop
	// close negotiation which require a clean channel state.
	ShutdownIfChannelClean() error
}

ChannelUpdateHandler is an interface that provides methods that allow sending lnwire.Message to the underlying link as well as querying state.

type CircuitFwdActions

type CircuitFwdActions struct {
	// Adds is the subsequence of circuits that were successfully committed
	// in the circuit map.
	Adds []*PaymentCircuit

	// Drops is the subsequence of circuits for which no action should be
	// done.
	Drops []*PaymentCircuit

	// Fails is the subsequence of circuits that should be failed back by
	// the calling link.
	Fails []*PaymentCircuit
}

CircuitFwdActions represents the forwarding decision made by the circuit map, and is returned from CommitCircuits. The sequence of circuits provided to CommitCircuits is split into three sub-sequences, allowing the caller to do an in-order scan, comparing the head of each subsequence, to determine the decision made by the circuit map.

type CircuitKey

type CircuitKey = models.CircuitKey

CircuitKey is a tuple of channel ID and HTLC ID, used to uniquely identify HTLCs in a circuit. Circuits are identified primarily by the circuit key of the incoming HTLC. However, a circuit may also be referenced by its outgoing circuit key after the HTLC has been forwarded via the outgoing link.

var EmptyCircuitKey CircuitKey

EmptyCircuitKey is a default value for an outgoing circuit key returned when a circuit's keystone has not been set. Note that this value is invalid for use as a keystone, since the outgoing channel id can never be equal to sourceHop.

type CircuitLookup

type CircuitLookup interface {
	// LookupCircuit queries the circuit map for the circuit identified by
	// inKey.
	LookupCircuit(inKey CircuitKey) *PaymentCircuit

	// LookupOpenCircuit queries the circuit map for a circuit identified
	// by its outgoing circuit key.
	LookupOpenCircuit(outKey CircuitKey) *PaymentCircuit
}

CircuitLookup is a common interface used to lookup information that is stored in the circuit map.

type CircuitMap

type CircuitMap interface {
	CircuitModifier

	CircuitLookup

	// CommitCircuits attempts to add the given circuits to the circuit
	// map. The list of circuits is split into three distinct
	// sub-sequences, corresponding to adds, drops, and fails. Adds should
	// be forwarded to the switch, while fails should be failed back
	// locally within the calling link.
	CommitCircuits(circuit ...*PaymentCircuit) (*CircuitFwdActions, error)

	// CloseCircuit marks the circuit identified by `outKey` as closing
	// in-memory, which prevents duplicate settles/fails from completing an
	// open circuit twice.
	CloseCircuit(outKey CircuitKey) (*PaymentCircuit, error)

	// FailCircuit is used by locally failed HTLCs to mark the circuit
	// identified by `inKey` as closing in-memory, which prevents duplicate
	// settles/fails from being accepted for the same circuit.
	FailCircuit(inKey CircuitKey) (*PaymentCircuit, error)

	// LookupByPaymentHash queries the circuit map and returns all open
	// circuits that use the given payment hash.
	LookupByPaymentHash(hash [32]byte) []*PaymentCircuit

	// NumPending returns the total number of active circuits added by
	// CommitCircuits.
	NumPending() int

	// NumOpen returns the number of circuits with HTLCs that have been
	// forwarded via an outgoing link.
	NumOpen() int
}

CircuitMap is an interface for managing the construction and teardown of payment circuits used by the switch.

func NewCircuitMap

func NewCircuitMap(cfg *CircuitMapConfig) (CircuitMap, error)

NewCircuitMap creates a new instance of the circuitMap.

type CircuitMapConfig

type CircuitMapConfig struct {
	// DB provides the persistent storage engine for the circuit map.
	DB kvdb.Backend

	// FetchAllOpenChannels is a function that fetches all currently open
	// channels from the channel database.
	FetchAllOpenChannels func() ([]*channeldb.OpenChannel, error)

	// FetchClosedChannels is a function that fetches all closed channels
	// from the channel database.
	FetchClosedChannels func(
		pendingOnly bool) ([]*channeldb.ChannelCloseSummary, error)

	// ExtractErrorEncrypter derives the shared secret used to encrypt
	// errors from the obfuscator's ephemeral public key.
	ExtractErrorEncrypter hop.ErrorEncrypterExtracter

	// CheckResolutionMsg checks whether a given resolution message exists
	// for the passed CircuitKey.
	CheckResolutionMsg func(outKey *CircuitKey) error
}

CircuitMapConfig houses the critical interfaces and references necessary to parameterize an instance of circuitMap.

type CircuitModifier

type CircuitModifier interface {
	// OpenCircuits preemptively records a batch keystones that will mark
	// currently pending circuits as open. These changes can be rolled back
	// on restart if the outgoing Adds do not make it into a commitment
	// txn.
	OpenCircuits(...Keystone) error

	// TrimOpenCircuits removes a channel's open channels with htlc indexes
	// above `start`.
	TrimOpenCircuits(chanID lnwire.ShortChannelID, start uint64) error

	// DeleteCircuits removes the incoming circuit key to remove all
	// persistent references to a circuit. Returns a ErrUnknownCircuit if
	// any of the incoming keys are not known.
	DeleteCircuits(inKeys ...CircuitKey) error
}

CircuitModifier is a common interface used by channel links to modify the contents of the circuit map maintained by the switch.

type ClearTextError

type ClearTextError interface {
	error

	// WireMessage extracts a valid wire failure message from an internal
	// error which may contain additional metadata (which should not be
	// exposed to the network). This value may be nil in the case where
	// an unknown wire error is returned by one of our peers.
	WireMessage() lnwire.FailureMessage
}

ClearTextError is an interface which is implemented by errors that occur when we know the underlying wire failure message. These errors are the opposite to opaque errors which are onion-encrypted blobs only understandable to the initiating node. ClearTextErrors are used when we fail a htlc at our node, or one of our initiated payments failed and we can decrypt the onion encrypted error fully.

type Config

type Config struct {
	// FwdingLog is an interface that will be used by the switch to log
	// forwarding events. A forwarding event happens each time a payment
	// circuit is successfully completed. So when we forward an HTLC, and a
	// settle is eventually received.
	FwdingLog ForwardingLog

	// LocalChannelClose kicks-off the workflow to execute a cooperative or
	// forced unilateral closure of the channel initiated by a local
	// subsystem.
	LocalChannelClose func(pubKey []byte, request *ChanClose)

	// DB is the database backend that will be used to back the switch's
	// persistent circuit map.
	DB kvdb.Backend

	// FetchAllOpenChannels is a function that fetches all currently open
	// channels from the channel database.
	FetchAllOpenChannels func() ([]*channeldb.OpenChannel, error)

	// FetchAllChannels is a function that fetches all pending open, open,
	// and waiting close channels from the database.
	FetchAllChannels func() ([]*channeldb.OpenChannel, error)

	// FetchClosedChannels is a function that fetches all closed channels
	// from the channel database.
	FetchClosedChannels func(
		pendingOnly bool) ([]*channeldb.ChannelCloseSummary, error)

	// SwitchPackager provides access to the forwarding packages of all
	// active channels. This gives the switch the ability to read arbitrary
	// forwarding packages, and ack settles and fails contained within them.
	SwitchPackager channeldb.FwdOperator

	// ExtractErrorEncrypter is an interface allowing switch to reextract
	// error encrypters stored in the circuit map on restarts, since they
	// are not stored directly within the database.
	ExtractErrorEncrypter hop.ErrorEncrypterExtracter

	// FetchLastChannelUpdate retrieves the latest routing policy for a
	// target channel. This channel will typically be the outgoing channel
	// specified when we receive an incoming HTLC.  This will be used to
	// provide payment senders our latest policy when sending encrypted
	// error messages.
	FetchLastChannelUpdate func(lnwire.ShortChannelID) (*lnwire.ChannelUpdate, error)

	// Notifier is an instance of a chain notifier that we'll use to signal
	// the switch when a new block has arrived.
	Notifier chainntnfs.ChainNotifier

	// HtlcNotifier is an instance of a htlcNotifier which we will pipe htlc
	// events through.
	HtlcNotifier htlcNotifier

	// FwdEventTicker is a signal that instructs the htlcswitch to flush any
	// pending forwarding events.
	FwdEventTicker ticker.Ticker

	// LogEventTicker is a signal instructing the htlcswitch to log
	// aggregate stats about it's forwarding during the last interval.
	LogEventTicker ticker.Ticker

	// AckEventTicker is a signal instructing the htlcswitch to ack any settle
	// fails in forwarding packages.
	AckEventTicker ticker.Ticker

	// AllowCircularRoute is true if the user has configured their node to
	// allow forwards that arrive and depart our node over the same channel.
	AllowCircularRoute bool

	// RejectHTLC is a flag that instructs the htlcswitch to reject any
	// HTLCs that are not from the source hop.
	RejectHTLC bool

	// Clock is a time source for the switch.
	Clock clock.Clock

	// MailboxDeliveryTimeout is the interval after which Adds will be
	// cancelled if they have not been yet been delivered to a link. The
	// computed deadline will expiry this long after the Adds are added to
	// a mailbox via AddPacket.
	MailboxDeliveryTimeout time.Duration

	// DustThreshold is the threshold in milli-satoshis after which we'll
	// fail incoming or outgoing dust payments for a particular channel.
	DustThreshold lnwire.MilliSatoshi

	// SignAliasUpdate is used when sending FailureMessages backwards for
	// option_scid_alias channels. This avoids a potential privacy leak by
	// replacing the public, confirmed SCID with the alias in the
	// ChannelUpdate.
	SignAliasUpdate func(u *lnwire.ChannelUpdate) (*ecdsa.Signature,
		error)

	// IsAlias returns whether or not a given SCID is an alias.
	IsAlias func(scid lnwire.ShortChannelID) bool
}

Config defines the configuration for the service. ALL elements within the configuration MUST be non-nil for the service to carry out its duties.

type DecayedLog

type DecayedLog struct {
	// contains filtered or unexported fields
}

DecayedLog implements the PersistLog interface. It stores the first HashPrefixSize bytes of a sha256-hashed shared secret along with a node's CLTV value. It is a decaying log meaning there will be a garbage collector to collect entries which are expired according to their stored CLTV value and the current block height. DecayedLog wraps boltdb for simplicity and batches writes to the database to decrease write contention.

func NewDecayedLog

func NewDecayedLog(db kvdb.Backend,
	notifier chainntnfs.ChainNotifier) *DecayedLog

NewDecayedLog creates a new DecayedLog, which caches recently seen hash shared secrets. Entries are evicted as their cltv expires using block epochs from the given notifier.

func (*DecayedLog) Delete

func (d *DecayedLog) Delete(hash *sphinx.HashPrefix) error

Delete removes a <shared secret hash, CLTV> key-pair from the sharedHashBucket.

func (*DecayedLog) Get

func (d *DecayedLog) Get(hash *sphinx.HashPrefix) (uint32, error)

Get retrieves the CLTV of a processed HTLC given the first 20 bytes of the Sha-256 hash of the shared secret.

func (*DecayedLog) Put

func (d *DecayedLog) Put(hash *sphinx.HashPrefix, cltv uint32) error

Put stores a shared secret hash as the key and the CLTV as the value.

func (*DecayedLog) PutBatch

func (d *DecayedLog) PutBatch(b *sphinx.Batch) (*sphinx.ReplaySet, error)

PutBatch accepts a pending batch of hashed secret entries to write to disk. Each hashed secret is inserted with a corresponding time value, dictating when the entry will be evicted from the log. NOTE: This method enforces idempotency by writing the replay set obtained from the first attempt for a particular batch ID, and decoding the return value to subsequent calls. For the indices of the replay set to be aligned properly, the batch MUST be constructed identically to the first attempt, pruning will cause the indices to become invalid.

func (*DecayedLog) Start

func (d *DecayedLog) Start() error

Start opens the database we will be using to store hashed shared secrets. It also starts the garbage collector in a goroutine to remove stale database entries.

func (*DecayedLog) Stop

func (d *DecayedLog) Stop() error

Stop halts the garbage collector and closes boltdb.

type ErrorDecrypter

type ErrorDecrypter interface {
	// DecryptError peels off each layer of onion encryption from the first
	// hop, to the source of the error. A fully populated
	// lnwire.FailureMessage is returned along with the source of the
	// error.
	DecryptError(lnwire.OpaqueReason) (*ForwardingError, error)
}

ErrorDecrypter is an interface that is used to decrypt the onion encrypted failure reason an extra out a well formed error.

type FailureDetail

type FailureDetail interface {
	// FailureString returns the string representation of a failure
	// detail.
	FailureString() string
}

FailureDetail is an interface implemented by failures that occur on our incoming or outgoing link, or within the switch itself.

type FinalHtlcEvent

type FinalHtlcEvent struct {
	CircuitKey

	Settled bool

	// Offchain is indicating whether the htlc was resolved off-chain.
	Offchain bool

	// Timestamp is the time when this htlc was settled.
	Timestamp time.Time
}

type ForwardInterceptor

type ForwardInterceptor func(InterceptedPacket) error

ForwardInterceptor is a function that is invoked from the switch for every incoming htlc that is intended to be forwarded. It is passed with the InterceptedForward that contains the information about the packet and a way to resolve it manually later in case it is held. The return value indicates if this handler will take control of this forward and resolve it later or let the switch execute its default behavior.

type ForwardingError

type ForwardingError struct {
	// FailureSourceIdx is the index of the node that sent the failure. With
	// this information, the dispatcher of a payment can modify their set of
	// candidate routes in response to the type of failure extracted. Index
	// zero is the self node.
	FailureSourceIdx int
	// contains filtered or unexported fields
}

ForwardingError wraps an lnwire.FailureMessage in a struct that also includes the source of the error.

func NewForwardingError

func NewForwardingError(failure lnwire.FailureMessage,
	index int) *ForwardingError

NewForwardingError creates a new payment error which wraps a wire error with additional metadata.

func NewUnknownForwardingError

func NewUnknownForwardingError(index int) *ForwardingError

NewUnknownForwardingError returns a forwarding error which has a nil failure message. This constructor should only be used in the case where we cannot decode the failure we have received from a peer.

func (*ForwardingError) Error

func (f *ForwardingError) Error() string

Error implements the built-in error interface. We use this method to allow the switch or any callers to insert additional context to the error message returned.

func (*ForwardingError) WireMessage

func (f *ForwardingError) WireMessage() lnwire.FailureMessage

WireMessage extracts a valid wire failure message from an internal error which may contain additional metadata (which should not be exposed to the network). This value may be nil in the case where an unknown wire error is returned by one of our peers.

Note this is part of the ClearTextError interface.

type ForwardingEvent

type ForwardingEvent struct {
	// HtlcKey uniquely identifies the htlc, and can be used to match the
	// forwarding event with subsequent settle/fail events.
	HtlcKey

	// HtlcInfo contains details about the htlc.
	HtlcInfo

	// HtlcEventType classifies the event as part of a local send or
	// receive, or as part of a forward.
	HtlcEventType

	// Timestamp is the time when this htlc was forwarded.
	Timestamp time.Time
}

ForwardingEvent represents a htlc that was forwarded onwards from our node. Sends which originate from our node will report forward events with zero incoming circuits in their htlc key.

type ForwardingFailEvent

type ForwardingFailEvent struct {
	// HtlcKey uniquely identifies the htlc, and can be used to match the
	// htlc with its corresponding forwarding event.
	HtlcKey

	// HtlcEventType classifies the event as part of a local send or
	// receive, or as part of a forward.
	HtlcEventType

	// Timestamp is the time when the forwarding failure was received.
	Timestamp time.Time
}

ForwardingFailEvent represents a htlc failure which occurred down the line after we forwarded a htlc onwards. An error is not included in this event because errors returned down the route are encrypted. HtlcInfo is not reliably available for forwarding failures, so it is omitted. These events should be matched with their corresponding forward event to obtain this information.

type ForwardingLog

type ForwardingLog interface {
	// AddForwardingEvents is a method that should write out the set of
	// forwarding events in a batch to persistent storage. Outside
	// sub-systems can then query the contents of the log for analysis,
	// visualizations, etc.
	AddForwardingEvents([]channeldb.ForwardingEvent) error
}

ForwardingLog is an interface that represents a time series database which keep track of all successfully completed payment circuits. Every few seconds, the switch will collate and flush out all the successful payment circuits during the last interval.

type FwdAction

type FwdAction int

FwdAction defines the various resolution types.

const (
	// FwdActionResume forwards the intercepted packet to the switch.
	FwdActionResume FwdAction = iota

	// FwdActionSettle settles the intercepted packet with a preimage.
	FwdActionSettle

	// FwdActionFail fails the intercepted packet back to the sender.
	FwdActionFail
)

type FwdResolution

type FwdResolution struct {
	// Key is the incoming circuit key of the htlc.
	Key models.CircuitKey

	// Action is the action to take on the intercepted htlc.
	Action FwdAction

	// Preimage is the preimage that is to be used for settling if Action is
	// FwdActionSettle.
	Preimage lntypes.Preimage

	// FailureMessage is the encrypted failure message that is to be passed
	// back to the sender if action is FwdActionFail.
	FailureMessage []byte

	// FailureCode is the failure code that is to be passed back to the
	// sender if action is FwdActionFail.
	FailureCode lnwire.FailCode
}

FwdResolution defines the action to be taken on an intercepted packet.

type HtlcEventType

type HtlcEventType int

HtlcEventType represents the type of event that a htlc was part of.

const (
	// HtlcEventTypeSend represents a htlc that was part of a send from
	// our node.
	HtlcEventTypeSend HtlcEventType = iota

	// HtlcEventTypeReceive represents a htlc that was part of a receive
	// to our node.
	HtlcEventTypeReceive

	// HtlcEventTypeForward represents a htlc that was forwarded through
	// our node.
	HtlcEventTypeForward
)

func (HtlcEventType) String

func (h HtlcEventType) String() string

String returns a string representation of a htlc event type.

type HtlcInfo

type HtlcInfo struct {
	// IncomingTimelock is the time lock of the htlc on our incoming
	// channel.
	IncomingTimeLock uint32

	// OutgoingTimelock is the time lock the htlc on our outgoing channel.
	OutgoingTimeLock uint32

	// IncomingAmt is the amount of the htlc on our incoming channel.
	IncomingAmt lnwire.MilliSatoshi

	// OutgoingAmt is the amount of the htlc on our outgoing channel.
	OutgoingAmt lnwire.MilliSatoshi
}

HtlcInfo provides the details of a htlc that our node has processed. For forwards, incoming and outgoing values are set, whereas sends and receives will only have outgoing or incoming details set.

func (HtlcInfo) String

func (h HtlcInfo) String() string

String returns a string representation of a htlc.

type HtlcKey

type HtlcKey struct {
	// IncomingCircuit is the channel an htlc id of the incoming htlc.
	IncomingCircuit models.CircuitKey

	// OutgoingCircuit is the channel and htlc id of the outgoing htlc.
	OutgoingCircuit models.CircuitKey
}

HtlcKey uniquely identifies the htlc.

func (HtlcKey) String

func (k HtlcKey) String() string

String returns a string representation of a htlc key.

type HtlcNotifier

type HtlcNotifier struct {
	// contains filtered or unexported fields
}

HtlcNotifier notifies clients of htlc forwards, failures and settles for htlcs that the switch handles. It takes subscriptions for its events and notifies them when htlc events occur. These are served on a best-effort basis; events are not persisted, delivery is not guaranteed (in the event of a crash in the switch, forward events may be lost) and some events may be replayed upon restart. Events consumed from this package should be de-duplicated by the htlc's unique combination of incoming+outgoing circuit and not relied upon for critical operations.

The htlc notifier sends the following kinds of events: Forwarding Event: - Represents a htlc which is forwarded onward from our node. - Present for htlc forwards through our node and local sends.

Link Failure Event:

  • Indicates that a htlc has failed on our incoming or outgoing link, with an incoming boolean which indicates where the failure occurred.
  • Incoming link failures are present for failed attempts to pay one of our invoices (insufficient amount or mpp timeout, for example) and for forwards that we cannot decode to forward onwards.
  • Outgoing link failures are present for forwards or local payments that do not meet our outgoing link's policy (insufficient fees, for example) and when we fail to forward the payment on (insufficient outgoing capacity, or an unknown outgoing link).

Forwarding Failure Event:

  • Forwarding failures indicate that a htlc we forwarded has failed at another node down the route.
  • Present for local sends and htlc forwards which fail after they left our node.

Settle event:

  • Settle events are present when a htlc which we added is settled through the release of a preimage.
  • Present for local receives, and successful local sends or forwards.

Each htlc is identified by its incoming and outgoing circuit key. Htlcs, and their subsequent settles or fails, can be identified by the combination of incoming and outgoing circuits. Note that receives to our node will have a zero outgoing circuit key because the htlc terminates at our node, and sends from our node will have a zero incoming circuit key because the send originates at our node.

func NewHtlcNotifier

func NewHtlcNotifier(now func() time.Time) *HtlcNotifier

NewHtlcNotifier creates a new HtlcNotifier which gets htlc forwarded, failed and settled events from links our node has established with peers and sends notifications to subscribing clients.

func (*HtlcNotifier) NotifyFinalHtlcEvent

func (h *HtlcNotifier) NotifyFinalHtlcEvent(key models.CircuitKey,
	info channeldb.FinalHtlcInfo)

NotifyFinalHtlcEvent notifies the HtlcNotifier that the final outcome for an htlc has been determined.

Note this is part of the htlcNotifier interface.

func (*HtlcNotifier) NotifyForwardingEvent

func (h *HtlcNotifier) NotifyForwardingEvent(key HtlcKey, info HtlcInfo,
	eventType HtlcEventType)

NotifyForwardingEvent notifies the HtlcNotifier than a htlc has been forwarded.

Note this is part of the htlcNotifier interface.

func (*HtlcNotifier) NotifyForwardingFailEvent

func (h *HtlcNotifier) NotifyForwardingFailEvent(key HtlcKey,
	eventType HtlcEventType)

NotifyForwardingFailEvent notifies the HtlcNotifier that a htlc we forwarded has failed down the line.

Note this is part of the htlcNotifier interface.

func (*HtlcNotifier) NotifyLinkFailEvent

func (h *HtlcNotifier) NotifyLinkFailEvent(key HtlcKey, info HtlcInfo,
	eventType HtlcEventType, linkErr *LinkError, incoming bool)

NotifyLinkFailEvent notifies that a htlc has failed on our incoming or outgoing link.

Note this is part of the htlcNotifier interface.

func (*HtlcNotifier) NotifySettleEvent

func (h *HtlcNotifier) NotifySettleEvent(key HtlcKey,
	preimage lntypes.Preimage, eventType HtlcEventType)

NotifySettleEvent notifies the HtlcNotifier that a htlc that we committed to as part of a forward or a receive to our node has been settled.

Note this is part of the htlcNotifier interface.

func (*HtlcNotifier) Start

func (h *HtlcNotifier) Start() error

Start starts the HtlcNotifier and all goroutines it needs to consume events and provide subscriptions to clients.

func (*HtlcNotifier) Stop

func (h *HtlcNotifier) Stop() error

Stop signals the notifier for a graceful shutdown.

func (*HtlcNotifier) SubscribeHtlcEvents

func (h *HtlcNotifier) SubscribeHtlcEvents() (*subscribe.Client, error)

SubscribeHtlcEvents returns a subscribe.Client that will receive updates any time the server is made aware of a new event.

type InterceptableHtlcForwarder

type InterceptableHtlcForwarder interface {
	// SetInterceptor sets a ForwardInterceptor.
	SetInterceptor(interceptor ForwardInterceptor)

	// Resolve resolves an intercepted packet.
	Resolve(res *FwdResolution) error
}

InterceptableHtlcForwarder is the interface to set the interceptor implementation that intercepts htlc forwards.

type InterceptableSwitch

type InterceptableSwitch struct {
	// contains filtered or unexported fields
}

InterceptableSwitch is an implementation of ForwardingSwitch interface. This implementation is used like a proxy that wraps the switch and intercepts forward requests. A reference to the Switch is held in order to communicate back the interception result where the options are: Resume - forwards the original request to the switch as is. Settle - routes UpdateFulfillHTLC to the originating link. Fail - routes UpdateFailHTLC to the originating link.

func NewInterceptableSwitch

func NewInterceptableSwitch(cfg *InterceptableSwitchConfig) (
	*InterceptableSwitch, error)

NewInterceptableSwitch returns an instance of InterceptableSwitch.

func (*InterceptableSwitch) ForwardPacket

func (s *InterceptableSwitch) ForwardPacket(
	fwd InterceptedForward) error

ForwardPacket forwards a single htlc to the external interceptor.

func (*InterceptableSwitch) ForwardPackets

func (s *InterceptableSwitch) ForwardPackets(linkQuit chan struct{}, isReplay bool,
	packets ...*htlcPacket) error

ForwardPackets attempts to forward the batch of htlcs to a connected interceptor. If the interceptor signals the resume action, the htlcs are forwarded to the switch. The link's quit signal should be provided to allow cancellation of forwarding during link shutdown.

func (*InterceptableSwitch) Resolve

func (s *InterceptableSwitch) Resolve(res *FwdResolution) error

Resolve resolves an intercepted packet.

func (*InterceptableSwitch) SetInterceptor

func (s *InterceptableSwitch) SetInterceptor(
	interceptor ForwardInterceptor)

SetInterceptor sets the ForwardInterceptor to be used. A nil argument unregisters the current interceptor.

func (*InterceptableSwitch) Start

func (s *InterceptableSwitch) Start() error

func (*InterceptableSwitch) Stop

func (s *InterceptableSwitch) Stop() error

type InterceptableSwitchConfig

type InterceptableSwitchConfig struct {
	// Switch is a reference to the actual switch implementation that
	// packets get sent to on resume.
	Switch *Switch

	// Notifier is an instance of a chain notifier that we'll use to signal
	// the switch when a new block has arrived.
	Notifier chainntnfs.ChainNotifier

	// CltvRejectDelta defines the number of blocks before the expiry of the
	// htlc where we auto-fail an intercepted htlc to prevent channel
	// force-closure.
	CltvRejectDelta uint32

	// CltvInterceptDelta defines the number of blocks before the expiry of
	// the htlc where we don't intercept anymore. This value must be greater
	// than CltvRejectDelta, because we don't want to offer htlcs to the
	// interceptor client for which there is no time left to resolve them
	// anymore.
	CltvInterceptDelta uint32

	// RequireInterceptor indicates whether processing should block if no
	// interceptor is connected.
	RequireInterceptor bool
}

InterceptableSwitchConfig contains the configuration of InterceptableSwitch.

type InterceptedForward

type InterceptedForward interface {
	// Packet returns the intercepted packet.
	Packet() InterceptedPacket

	// Resume notifies the intention to resume an existing hold forward. This
	// basically means the caller wants to resume with the default behavior for
	// this htlc which usually means forward it.
	Resume() error

	// Settle notifies the intention to settle an existing hold
	// forward with a given preimage.
	Settle(lntypes.Preimage) error

	// Fail notifies the intention to fail an existing hold forward with an
	// encrypted failure reason.
	Fail(reason []byte) error

	// FailWithCode notifies the intention to fail an existing hold forward
	// with the specified failure code.
	FailWithCode(code lnwire.FailCode) error
}

InterceptedForward is passed to the ForwardInterceptor for every forwarded htlc. It contains all the information about the packet which accordingly the interceptor decides if to hold or not. In addition this interface allows a later resolution by calling either Resume, Settle or Fail.

type InterceptedPacket

type InterceptedPacket struct {
	// IncomingCircuit contains the incoming channel and htlc id of the
	// packet.
	IncomingCircuit models.CircuitKey

	// OutgoingChanID is the destination channel for this packet.
	OutgoingChanID lnwire.ShortChannelID

	// Hash is the payment hash of the htlc.
	Hash lntypes.Hash

	// OutgoingExpiry is the absolute block height at which the outgoing
	// htlc expires.
	OutgoingExpiry uint32

	// OutgoingAmount is the amount to forward.
	OutgoingAmount lnwire.MilliSatoshi

	// IncomingExpiry is the absolute block height at which the incoming
	// htlc expires.
	IncomingExpiry uint32

	// IncomingAmount is the amount of the accepted htlc.
	IncomingAmount lnwire.MilliSatoshi

	// CustomRecords are user-defined records in the custom type range that
	// were included in the payload.
	CustomRecords record.CustomSet

	// OnionBlob is the onion packet for the next hop
	OnionBlob [lnwire.OnionPacketSize]byte

	// AutoFailHeight is the block height at which this intercept will be
	// failed back automatically.
	AutoFailHeight int32
}

InterceptedPacket contains the relevant information for the interceptor about an htlc.

type InvoiceDatabase

type InvoiceDatabase interface {
	// LookupInvoice attempts to look up an invoice according to its 32
	// byte payment hash.
	LookupInvoice(lntypes.Hash) (invoices.Invoice, error)

	// NotifyExitHopHtlc attempts to mark an invoice as settled. If the
	// invoice is a debug invoice, then this method is a noop as debug
	// invoices are never fully settled. The return value describes how the
	// htlc should be resolved. If the htlc cannot be resolved immediately,
	// the resolution is sent on the passed in hodlChan later. The eob
	// field passes the entire onion hop payload into the invoice registry
	// for decoding purposes.
	NotifyExitHopHtlc(payHash lntypes.Hash, paidAmount lnwire.MilliSatoshi,
		expiry uint32, currentHeight int32,
		circuitKey models.CircuitKey, hodlChan chan<- interface{},
		payload invoices.Payload) (invoices.HtlcResolution, error)

	// CancelInvoice attempts to cancel the invoice corresponding to the
	// passed payment hash.
	CancelInvoice(payHash lntypes.Hash) error

	// SettleHodlInvoice settles a hold invoice.
	SettleHodlInvoice(preimage lntypes.Preimage) error

	// HodlUnsubscribeAll unsubscribes from all htlc resolutions.
	HodlUnsubscribeAll(subscriber chan<- interface{})
}

InvoiceDatabase is an interface which represents the persistent subsystem which may search, lookup and settle invoices.

type Keystone

type Keystone struct {
	InKey  CircuitKey
	OutKey CircuitKey
}

Keystone is a tuple binding an incoming and outgoing CircuitKey. Keystones are preemptively written by an outgoing link before signing a new commitment state, and cements which HTLCs we are awaiting a response from a remote peer.

func (Keystone) String

func (k Keystone) String() string

String returns a human readable description of the Keystone.

type LinkError

type LinkError struct {

	// FailureDetail enriches the wire error with additional information.
	FailureDetail
	// contains filtered or unexported fields
}

LinkError is an implementation of the ClearTextError interface which represents failures that occur on our incoming or outgoing link.

func NewDetailedLinkError

func NewDetailedLinkError(msg lnwire.FailureMessage,
	detail FailureDetail) *LinkError

NewDetailedLinkError returns a link error that enriches a wire message with a failure detail.

func NewLinkError

func NewLinkError(msg lnwire.FailureMessage) *LinkError

NewLinkError returns a LinkError with the failure message provided. The failure message provided should *not* be nil, because we should always know the failure type for failures which occur at our own node.

func (*LinkError) Error

func (l *LinkError) Error() string

Error returns the string representation of a link error.

Note this is part of the ClearTextError interface.

func (*LinkError) WireMessage

func (l *LinkError) WireMessage() lnwire.FailureMessage

WireMessage extracts a valid wire failure message from an internal error which may contain additional metadata (which should not be exposed to the network). This value should never be nil for LinkErrors, because we are the ones failing the htlc.

Note this is part of the ClearTextError interface.

type LinkFailEvent

type LinkFailEvent struct {
	// HtlcKey uniquely identifies the htlc.
	HtlcKey

	// HtlcInfo contains details about the htlc.
	HtlcInfo

	// HtlcEventType classifies the event as part of a local send or
	// receive, or as part of a forward.
	HtlcEventType

	// LinkError is the reason that we failed the htlc.
	LinkError *LinkError

	// Incoming is true if the htlc was failed on an incoming link.
	// If it failed on the outgoing link, it is false.
	Incoming bool

	// Timestamp is the time when the link failure occurred.
	Timestamp time.Time
}

LinkFailEvent describes a htlc that failed on our incoming or outgoing link. The incoming bool is true for failures on incoming links, and false for failures on outgoing links. The failure reason is provided by a lnwire failure message which is enriched with a failure detail in the cases where the wire failure message does not contain full information about the failure.

type LinkFailureAction

type LinkFailureAction uint8

LinkFailureAction is an enum-like type that describes the action that should be taken in response to a link failure.

const (
	// LinkFailureForceNone indicates no action is to be taken.
	LinkFailureForceNone LinkFailureAction = iota

	// LinkFailureForceClose indicates that the channel should be force
	// closed.
	LinkFailureForceClose

	// LinkFailureDisconnect indicates that we should disconnect in an
	// attempt to recycle the connection. This can be useful if we think a
	// TCP connection or state machine is stalled.
	LinkFailureDisconnect
)

type LinkFailureError

type LinkFailureError struct {

	// FailureAction describes what we should do to fail the channel.
	FailureAction LinkFailureAction

	// PermanentFailure indicates whether this failure is permanent, and
	// the channel should not be attempted loaded again.
	PermanentFailure bool

	// Warning denotes if this is a non-terminal error that doesn't warrant
	// failing the channel all together.
	Warning bool

	// SendData is a byte slice that will be sent to the peer. If nil a
	// generic error will be sent.
	SendData []byte
	// contains filtered or unexported fields
}

LinkFailureError encapsulates an error that will make us fail the current link. It contains the necessary information needed to determine if we should force close the channel in the process, and if any error data should be sent to the peer.

func (LinkFailureError) Error

func (e LinkFailureError) Error() string

Error returns a generic error for the LinkFailureError.

NOTE: Part of the error interface.

func (LinkFailureError) ShouldSendToPeer

func (e LinkFailureError) ShouldSendToPeer() bool

ShouldSendToPeer indicates whether we should send an error to the peer if the link fails with this LinkFailureError.

type MailBox

type MailBox interface {
	// AddMessage appends a new message to the end of the message queue.
	AddMessage(msg lnwire.Message) error

	// AddPacket appends a new message to the end of the packet queue.
	AddPacket(pkt *htlcPacket) error

	// HasPacket queries the packets for a circuit key, this is used to drop
	// packets bound for the switch that already have a queued response.
	HasPacket(CircuitKey) bool

	// AckPacket removes a packet from the mailboxes in-memory replay
	// buffer. This will prevent a packet from being delivered after a link
	// restarts if the switch has remained online. The returned boolean
	// indicates whether or not a packet with the passed incoming circuit
	// key was removed.
	AckPacket(CircuitKey) bool

	// FailAdd fails an UpdateAddHTLC that exists within the mailbox,
	// removing it from the in-memory replay buffer. This will prevent the
	// packet from being delivered after the link restarts if the switch has
	// remained online. The generated LinkError will show an
	// OutgoingFailureDownstreamHtlcAdd FailureDetail.
	FailAdd(pkt *htlcPacket)

	// MessageOutBox returns a channel that any new messages ready for
	// delivery will be sent on.
	MessageOutBox() chan lnwire.Message

	// PacketOutBox returns a channel that any new packets ready for
	// delivery will be sent on.
	PacketOutBox() chan *htlcPacket

	// Clears any pending wire messages from the inbox.
	ResetMessages() error

	// Reset the packet head to point at the first element in the list.
	ResetPackets() error

	// SetDustClosure takes in a closure that is used to evaluate whether
	// mailbox HTLC's are dust.
	SetDustClosure(isDust dustClosure)

	// SetFeeRate sets the feerate to be used when evaluating dust.
	SetFeeRate(feerate chainfee.SatPerKWeight)

	// DustPackets returns the dust sum for Adds in the mailbox for the
	// local and remote commitments.
	DustPackets() (lnwire.MilliSatoshi, lnwire.MilliSatoshi)

	// Start starts the mailbox and any goroutines it needs to operate
	// properly.
	Start()

	// Stop signals the mailbox and its goroutines for a graceful shutdown.
	Stop()
}

MailBox is an interface which represents a concurrent-safe, in-order delivery queue for messages from the network and also from the main switch. This struct serves as a buffer between incoming messages, and messages to the handled by the link. Each of the mutating methods within this interface should be implemented in a non-blocking manner.

type OnionErrorDecrypter

type OnionErrorDecrypter interface {
	// DecryptError attempts to decrypt the passed encrypted error response.
	// The onion failure is encrypted in backward manner, starting from the
	// node where error have occurred. As a result, in order to decrypt the
	// error we need get all shared secret and apply decryption in the
	// reverse order.
	DecryptError(encryptedData []byte) (*sphinx.DecryptedError, error)
}

OnionErrorDecrypter is the interface that provides onion level error decryption.

type OutgoingFailure

type OutgoingFailure int

OutgoingFailure is an enum which is used to enrich failures which occur in the switch or on our outgoing link with additional metadata.

const (
	// OutgoingFailureNone is returned when the wire message contains
	// sufficient information.
	OutgoingFailureNone OutgoingFailure = iota

	// OutgoingFailureDecodeError indicates that we could not decode the
	// failure reason provided for a failed payment.
	OutgoingFailureDecodeError

	// OutgoingFailureLinkNotEligible indicates that a routing attempt was
	// made over a link that is not eligible for routing.
	OutgoingFailureLinkNotEligible

	// OutgoingFailureOnChainTimeout indicates that a payment had to be
	// timed out on chain before it got past the first hop by us or the
	// remote party.
	OutgoingFailureOnChainTimeout

	// OutgoingFailureHTLCExceedsMax is returned when a htlc exceeds our
	// policy's maximum htlc amount.
	OutgoingFailureHTLCExceedsMax

	// OutgoingFailureInsufficientBalance is returned when we cannot route a
	// htlc due to insufficient outgoing capacity.
	OutgoingFailureInsufficientBalance

	// OutgoingFailureCircularRoute is returned when an attempt is made
	// to forward a htlc through our node which arrives and leaves on the
	// same channel.
	OutgoingFailureCircularRoute

	// OutgoingFailureIncompleteForward is returned when we cancel an incomplete
	// forward.
	OutgoingFailureIncompleteForward

	// OutgoingFailureDownstreamHtlcAdd is returned when we fail to add a
	// downstream htlc to our outgoing link.
	OutgoingFailureDownstreamHtlcAdd

	// OutgoingFailureForwardsDisabled is returned when the switch is
	// configured to disallow forwards.
	OutgoingFailureForwardsDisabled
)

func (OutgoingFailure) FailureString

func (fd OutgoingFailure) FailureString() string

FailureString returns the string representation of a failure detail.

Note: it is part of the FailureDetail interface.

type PaymentCircuit

type PaymentCircuit struct {
	// AddRef is the forward reference of the Add update in the incoming
	// link's forwarding package. This value is set on the htlcPacket of the
	// returned settle/fail so that it can be removed from disk.
	AddRef channeldb.AddRef

	// Incoming is the circuit key identifying the incoming channel and htlc
	// index from which this ADD originates.
	Incoming CircuitKey

	// Outgoing is the circuit key identifying the outgoing channel, and the
	// HTLC index that was used to forward the ADD. It will be nil if this
	// circuit's keystone has not been set.
	Outgoing *CircuitKey

	// PaymentHash used as unique identifier of payment.
	PaymentHash [32]byte

	// IncomingAmount is the value of the HTLC from the incoming link.
	IncomingAmount lnwire.MilliSatoshi

	// OutgoingAmount specifies the value of the HTLC leaving the switch,
	// either as a payment or forwarded amount.
	OutgoingAmount lnwire.MilliSatoshi

	// ErrorEncrypter is used to re-encrypt the onion failure before
	// sending it back to the originator of the payment.
	ErrorEncrypter hop.ErrorEncrypter

	// LoadedFromDisk is set true for any circuits loaded after the circuit
	// map is reloaded from disk.
	//
	// NOTE: This value is determined implicitly during a restart. It is not
	// persisted, and should never be set outside the circuit map.
	LoadedFromDisk bool
}

PaymentCircuit is used by the switch as placeholder between when the switch makes a forwarding decision and the outgoing link determines the proper HTLC ID for the local log. After the outgoing HTLC ID has been determined, the half circuit will be converted into a full PaymentCircuit.

func (*PaymentCircuit) Decode

func (c *PaymentCircuit) Decode(r io.Reader) error

Decode reads a PaymentCircuit from the provided io.Reader.

func (*PaymentCircuit) Encode

func (c *PaymentCircuit) Encode(w io.Writer) error

Encode writes a PaymentCircuit to the provided io.Writer.

func (*PaymentCircuit) HasKeystone

func (c *PaymentCircuit) HasKeystone() bool

HasKeystone returns true if an outgoing link has assigned this circuit's outgoing circuit key.

func (*PaymentCircuit) InKey

func (c *PaymentCircuit) InKey() CircuitKey

InKey returns the primary identifier for the circuit corresponding to the incoming HTLC.

func (*PaymentCircuit) OutKey

func (c *PaymentCircuit) OutKey() CircuitKey

OutKey returns the keystone identifying the outgoing link and HTLC ID. If the circuit hasn't been completed, this method returns an EmptyKeystone, which is an invalid outgoing circuit key. Only call this method if HasKeystone returns true.

type PaymentResult

type PaymentResult struct {
	// Preimage is set by the switch in case a sent HTLC was settled.
	Preimage [32]byte

	// Error is non-nil in case a HTLC send failed, and the HTLC is now
	// irrevocably canceled. If the payment failed during forwarding, this
	// error will be a *ForwardingError.
	Error error
}

PaymentResult wraps a decoded result received from the network after a payment attempt was made. This is what is eventually handed to the router for processing.

type Sequencer

type Sequencer interface {
	// NextID returns a unique sequence number for each invocation.
	NextID() (uint64, error)
}

Sequencer emits sequence numbers for locally initiated HTLCs. These are only used internally for tracking pending payments, however they must be unique in order to avoid circuit key collision in the circuit map.

func NewPersistentSequencer

func NewPersistentSequencer(db *channeldb.DB) (Sequencer, error)

NewPersistentSequencer initializes a new sequencer using a channeldb backend.

type SettleEvent

type SettleEvent struct {
	// HtlcKey uniquely identifies the htlc, and can be used to match
	// forwards with their corresponding forwarding event.
	HtlcKey

	// Preimage that was released for settling the htlc.
	Preimage lntypes.Preimage

	// HtlcEventType classifies the event as part of a local send or
	// receive, or as part of a forward.
	HtlcEventType

	// Timestamp is the time when this htlc was settled.
	Timestamp time.Time
}

SettleEvent represents a htlc that was settled. HtlcInfo is not reliably available for forwarding failures, so it is omitted. These events should be matched with corresponding forward events or invoices (for receives) to obtain additional information about the htlc.

type SphinxErrorDecrypter

type SphinxErrorDecrypter struct {
	OnionErrorDecrypter
}

SphinxErrorDecrypter wraps the sphinx data SphinxErrorDecrypter and maps the returned errors to concrete lnwire.FailureMessage instances.

func (*SphinxErrorDecrypter) DecryptError

func (s *SphinxErrorDecrypter) DecryptError(reason lnwire.OpaqueReason) (
	*ForwardingError, error)

DecryptError peels off each layer of onion encryption from the first hop, to the source of the error. A fully populated lnwire.FailureMessage is returned along with the source of the error.

NOTE: Part of the ErrorDecrypter interface.

type Switch

type Switch struct {
	// contains filtered or unexported fields
}

Switch is the central messaging bus for all incoming/outgoing HTLCs. Connected peers with active channels are treated as named interfaces which refer to active channels as links. A link is the switch's message communication point with the goroutine that manages an active channel. New links are registered each time a channel is created, and unregistered once the channel is closed. The switch manages the hand-off process for multi-hop HTLCs, forwarding HTLCs initiated from within the daemon, and finally notifies users local-systems concerning their outstanding payment requests.

func New

func New(cfg Config, currentHeight uint32) (*Switch, error)

New creates the new instance of htlc switch.

func (s *Switch) AddAliasForLink(chanID lnwire.ChannelID,
	alias lnwire.ShortChannelID) error

AddAliasForLink instructs the Switch to update its in-memory maps to reflect that a link has a new alias.

func (s *Switch) AddLink(link ChannelLink) error

AddLink is used to initiate the handling of the add link command. The request will be propagated and handled in the main goroutine.

func (*Switch) BestHeight

func (s *Switch) BestHeight() uint32

BestHeight returns the best height known to the switch.

func (*Switch) CircuitLookup

func (s *Switch) CircuitLookup() CircuitLookup

CircuitLookup returns a reference to subset of the interfaces provided by the circuit map, to allow looking up circuits.

func (*Switch) CircuitModifier

func (s *Switch) CircuitModifier() CircuitModifier

CircuitModifier returns a reference to subset of the interfaces provided by the circuit map, to allow links to open and close circuits.

func (*Switch) CleanStore

func (s *Switch) CleanStore(keepPids map[uint64]struct{}) error

CleanStore calls the underlying result store, telling it is safe to delete all entries except the ones in the keepPids map. This should be called preiodically to let the switch clean up payment results that we have handled.

func (s *Switch) CloseLink(chanPoint *wire.OutPoint,
	closeType contractcourt.ChannelCloseType,
	targetFeePerKw, maxFee chainfee.SatPerKWeight,
	deliveryScript lnwire.DeliveryAddress) (chan interface{}, chan error)

CloseLink creates and sends the close channel command to the target link directing the specified closure type. If the closure type is CloseRegular, targetFeePerKw parameter should be the ideal fee-per-kw that will be used as a starting point for close negotiation. The deliveryScript parameter is an optional parameter which sets a user specified script to close out to.

func (s *Switch) CreateAndAddLink(linkCfg ChannelLinkConfig,
	lnChan *lnwallet.LightningChannel) error

CreateAndAddLink will create a link and then add it to the internal maps when given a ChannelLinkConfig and LightningChannel.

func (*Switch) FlushForwardingEvents

func (s *Switch) FlushForwardingEvents() error

FlushForwardingEvents flushes out the set of pending forwarding events to the persistent log. This will be used by the switch to periodically flush out the set of forwarding events to disk. External callers can also use this method to ensure all data is flushed to dis before querying the log.

func (*Switch) ForwardPackets

func (s *Switch) ForwardPackets(linkQuit chan struct{},
	packets ...*htlcPacket) error

ForwardPackets adds a list of packets to the switch for processing. Fails and settles are added on a first past, simultaneously constructing circuits for any adds. After persisting the circuits, another pass of the adds is given to forward them through the router. The sending link's quit channel is used to prevent deadlocks when the switch stops a link in the midst of forwarding.

func (*Switch) GetAttemptResult

func (s *Switch) GetAttemptResult(attemptID uint64, paymentHash lntypes.Hash,
	deobfuscator ErrorDecrypter) (<-chan *PaymentResult, error)

GetAttemptResult returns the result of the payment attempt with the given attemptID. The paymentHash should be set to the payment's overall hash, or in case of AMP payments the payment's unique identifier.

The method returns a channel where the payment result will be sent when available, or an error is encountered during forwarding. When a result is received on the channel, the HTLC is guaranteed to no longer be in flight. The switch shutting down is signaled by closing the channel. If the attemptID is unknown, ErrPaymentIDNotFound will be returned.

func (s *Switch) GetLink(chanID lnwire.ChannelID) (ChannelUpdateHandler,
	error)

GetLink is used to initiate the handling of the get link command. The request will be propagated/handled to/in the main goroutine.

func (*Switch) GetLinkByShortID

func (s *Switch) GetLinkByShortID(chanID lnwire.ShortChannelID) (ChannelLink,
	error)

GetLinkByShortID attempts to return the link which possesses the target short channel ID.

func (*Switch) GetLinksByInterface

func (s *Switch) GetLinksByInterface(hop [33]byte) ([]ChannelUpdateHandler,
	error)

GetLinksByInterface fetches all the links connected to a particular node identified by the serialized compressed form of its public key.

func (s *Switch) HasActiveLink(chanID lnwire.ChannelID) bool

HasActiveLink returns true if the given channel ID has a link in the link index AND the link is eligible to forward.

func (*Switch) IsForwardedHTLC

func (s *Switch) IsForwardedHTLC(chanID lnwire.ShortChannelID,
	htlcIndex uint64) bool

IsForwardedHTLC checks for a given channel and htlc index if it is related to an opened circuit that represents a forwarded payment.

func (*Switch) ProcessContractResolution

func (s *Switch) ProcessContractResolution(msg contractcourt.ResolutionMsg) error

ProcessContractResolution is called by active contract resolvers once a contract they are watching over has been fully resolved. The message carries an external signal that *would* have been sent if the outgoing channel didn't need to go to the chain in order to fulfill a contract. We'll process this message just as if it came from an active outgoing channel.

func (s *Switch) RemoveLink(chanID lnwire.ChannelID)

RemoveLink purges the switch of any link associated with chanID. If a pending or active link is not found, this method does nothing. Otherwise, the method returns after the link has been completely shutdown.

func (*Switch) SendHTLC

func (s *Switch) SendHTLC(firstHop lnwire.ShortChannelID, attemptID uint64,
	htlc *lnwire.UpdateAddHTLC) error

SendHTLC is used by other subsystems which aren't belong to htlc switch package in order to send the htlc update. The attemptID used MUST be unique for this HTLC, and MUST be used only once, otherwise the switch might reject it.

func (*Switch) Start

func (s *Switch) Start() error

Start starts all helper goroutines required for the operation of the switch.

func (*Switch) Stop

func (s *Switch) Stop() error

Stop gracefully stops all active helper goroutines, then waits until they've exited.

func (*Switch) UpdateForwardingPolicies

func (s *Switch) UpdateForwardingPolicies(
	chanPolicies map[wire.OutPoint]models.ForwardingPolicy)

UpdateForwardingPolicies sends a message to the switch to update the forwarding policies for the set of target channels, keyed in chanPolicies.

NOTE: This function is synchronous and will block until either the forwarding policies for all links have been updated, or the switch shuts down.

func (*Switch) UpdateShortChanID

func (s *Switch) UpdateShortChanID(chanID lnwire.ChannelID) error

UpdateShortChanID locates the link with the passed-in chanID and updates the underlying channel state. This is only used in zero-conf channels to allow the confirmed SCID to be updated.

type TowerClient

type TowerClient interface {
	// RegisterChannel persistently initializes any channel-dependent
	// parameters within the client. This should be called during link
	// startup to ensure that the client is able to support the link during
	// operation.
	RegisterChannel(lnwire.ChannelID) error

	// BackupState initiates a request to back up a particular revoked
	// state. If the method returns nil, the backup is guaranteed to be
	// successful unless the justice transaction would create dust outputs
	// when trying to abide by the negotiated policy.
	BackupState(chanID *lnwire.ChannelID, stateNum uint64) error
}

TowerClient is the primary interface used by the daemon to backup pre-signed justice transactions to watchtowers.

type UnknownEncrypterType

type UnknownEncrypterType hop.EncrypterType

UnknownEncrypterType is an error message used to signal that an unexpected EncrypterType was encountered during decoding.

func (UnknownEncrypterType) Error

func (e UnknownEncrypterType) Error() string

Error returns a formatted error indicating the invalid EncrypterType.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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