htlcswitch

package
v0.4.2-beta Latest Latest
Warning

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

Go to latest
Published: May 29, 2018 License: MIT Imports: 36 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// EncrypterTypeNone signals that no error encyrpter is present, this
	// can happen if the htlc is originates in the switch.
	EncrypterTypeNone EncrypterType = 0

	// EncrypterTypeSphinx is used to identify a sphinx onion error
	// encrypter instance.
	EncrypterTypeSphinx = 1

	// EncrypterTypeMock is used to identify a mock obfuscator instance.
	EncrypterTypeMock = 2
)
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

	// 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
)

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 (
	// 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")

	// ErrIncompleteForward is used when an htlc was already forwarded
	// through the switch, but did not get locked into another commitment
	// txn.
	ErrIncompleteForward = errors.Errorf("incomplete forward detected")
)
View Source
var (
	// ErrLinkShuttingDown signals that the link is shutting down.
	ErrLinkShuttingDown = errors.New("link shutting down")
)
View Source
var ErrMailBoxShuttingDown = errors.New("mailbox is shutting down")

ErrMailBoxShuttingDown is returned when the mailbox is interrupted by a shutdown request.

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

func ExpectedFee(f ForwardingPolicy,
	htlcAmt lnwire.MilliSatoshi) lnwire.MilliSatoshi

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 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 BatchTicker

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

BatchTicker implements the Ticker interface, and wraps a time.Ticker.

func NewBatchTicker

func NewBatchTicker(t *time.Ticker) *BatchTicker

NewBatchTicker returns a new BatchTicker that wraps the passed time.Ticker.

func (*BatchTicker) Start

func (t *BatchTicker) Start() <-chan time.Time

Start returns the tick channel for the underlying time.Ticker.

func (*BatchTicker) Stop

func (t *BatchTicker) Stop()

Stop stops the underlying time.Ticker.

type ChanClose

type ChanClose struct {
	// CloseType is a variable which signals the type of channel closure the
	// peer should execute.
	CloseType 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 lnwallet.SatPerKWeight

	// Updates is used by request creator to receive the notifications about
	// execution of the close channel request.
	Updates chan *lnrpc.CloseStatusUpdate

	// 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 ChannelCloseType

type ChannelCloseType uint8

ChannelCloseType is an enum which signals the type of channel closure the peer should execute.

const (
	// CloseRegular indicates a regular cooperative channel closure
	// should be attempted.
	CloseRegular ChannelCloseType = iota

	// CloseBreach indicates that a channel breach has been detected, and
	// the link should immediately be marked as unavailable.
	CloseBreach
)
type ChannelLink interface {

	// HandleSwitchPacket handles the switch packets. This packets might be
	// forwarded to us from another channel link in case the htlc update
	// came from another peer or if the update was created by user
	// initially.
	//
	// NOTE: This function MUST be non-blocking (or block as little as
	// possible).
	HandleSwitchPacket(*htlcPacket) error

	// 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

	// 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(ForwardingPolicy)

	// HtlcSatifiesPolicy should return a nil error if the passed HTLC
	// details satisfy the current forwarding policy fo the target link.
	// Otherwise, a valid protocol failure message should be returned in
	// order to signal to the source of the HTLC, the policy consistency
	// issue.
	HtlcSatifiesPolicy(payHash [32]byte,
		incomingAmt, amtToForward lnwire.MilliSatoshi) lnwire.FailureMessage

	// 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

	// 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() Peer

	// 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

	// 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()
}

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,
	currentHeight uint32) 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 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

	// ForwardPackets attempts to forward the batch of htlcs through the
	// switch. Any failed packets will be returned to the provided
	// ChannelLink.
	ForwardPackets func(...*htlcPacket) chan 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, []DecodeHopIteratorRequest) (
		[]DecodeHopIteratorResponse, error)

	// ExtractErrorEncrypter function is responsible for decoding HTLC
	// Sphinx onion blob, and creating onion failure obfuscator.
	ExtractErrorEncrypter 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 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 the latest signals for our inner Lightning
	// channel. These signals will notify the caller when the channel has
	// been closed, or when the set of active HTLC's is updated.
	UpdateContractSignals func(*contractcourt.ContractSignals) 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 lnwallet.FeeEstimator

	// BlockEpochs is an active block epoch event stream backed by an
	// active ChainNotifier instance. The ChannelLink will use new block
	// notifications sent over this channel to decide when a _new_ HTLC is
	// too close to expiry, and also when any active HTLC's have expired
	// (or are close to expiry).
	BlockEpochs *chainntnfs.BlockEpochEvent

	// DebugHTLC should be turned on if you want all HTLCs sent to a node
	// with the debug htlc R-Hash are immediately settled in the next
	// available state transition.
	DebugHTLC bool

	// 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, and should only be used
	// simultaneously with DebugHTLC.
	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

	// 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

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

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 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 = channeldb.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 CircuitMap

type CircuitMap interface {
	CircuitModifier

	// 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)

	// 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

	// 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.
	// TODO(conner): create abstraction to allow for the substitution of
	// other persistence engines.
	DB *channeldb.DB

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

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 Config

type Config struct {
	// SelfKey is the key of the backing Lightning node. This key is used
	// to properly craft failure messages, such that the Layer 3 router can
	// properly route around link./vertex failures.
	SelfKey *btcec.PublicKey

	// 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 channeldb instance that will be used to back the switch's
	// persistent circuit map.
	DB *channeldb.DB

	// 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 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)
}

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(dbPath string,
	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 DecodeHopIteratorRequest

type DecodeHopIteratorRequest struct {
	OnionReader  io.Reader
	RHash        []byte
	IncomingCltv uint32
}

DecodeHopIteratorRequest encapsulates all date necessary to process an onion packet, perform sphinx replay detection, and schedule the entry for garbage collection.

type DecodeHopIteratorResponse

type DecodeHopIteratorResponse struct {
	HopIterator HopIterator
	FailCode    lnwire.FailCode
}

DecodeHopIteratorResponse encapsulates the outcome of a batched sphinx onion processing.

func (*DecodeHopIteratorResponse) Result

Result returns the (HopIterator, lnwire.FailCode) tuple, which should correspond to the index of a particular DecodeHopIteratorRequest.

NOTE: The HopIterator should be considered invalid if the fail code is anything but lnwire.CodeNone.

type EncrypterType

type EncrypterType byte

EncrypterType establishes an enum used in serialization to indicate how to decode a concrete instance of the ErrorEncrypter interface.

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 ErrorEncrypter

type ErrorEncrypter interface {
	// EncryptFirstHop transforms a concrete failure message into an
	// encrypted opaque failure reason. This method will be used at the
	// source that the error occurs. It differs from IntermediateEncrypt
	// slightly, in that it computes a proper MAC over the error.
	EncryptFirstHop(lnwire.FailureMessage) (lnwire.OpaqueReason, error)

	// IntermediateEncrypt wraps an already encrypted opaque reason error
	// in an additional layer of onion encryption. This process repeats
	// until the error arrives at the source of the payment.
	IntermediateEncrypt(lnwire.OpaqueReason) lnwire.OpaqueReason

	// Type returns an enum indicating the underlying concrete instance
	// backing this interface.
	Type() EncrypterType

	// Encode serializes the encrypter's ephemeral public key to the given
	// io.Writer.
	Encode(io.Writer) error

	// Decode deserializes the encrypter' ephemeral public key from the
	// given io.Reader.
	Decode(io.Reader) error

	// Reextract rederives the encrypter using the extracter, performing an
	// ECDH with the sphinx router's key and the ephemeral public key.
	//
	// NOTE: This should be called shortly after Decode to properly
	// reinitialize the error encrypter.
	Reextract(ErrorEncrypterExtracter) error
}

ErrorEncrypter is an interface that is used to encrypt HTLC related errors at the source of the error, and also at each intermediate hop all the way back to the source of the payment.

func NewMockObfuscator

func NewMockObfuscator() ErrorEncrypter

NewMockObfuscator initializes a dummy mockObfuscator used for testing.

type ErrorEncrypterExtracter

type ErrorEncrypterExtracter func(*btcec.PublicKey) (ErrorEncrypter,
	lnwire.FailCode)

ErrorEncrypterExtracter defines a function signature that extracts an ErrorEncrypter from an sphinx OnionPacket.

type ForwardingError

type ForwardingError struct {
	// ErrorSource is the public key of the node that sent the error. With
	// this information, the dispatcher of a payment can modify their set
	// of candidate routes in response to the type of error extracted.
	ErrorSource *btcec.PublicKey

	// ExtraMsg is an additional error message that callers can provide in
	// order to provide context specific error details.
	ExtraMsg string

	lnwire.FailureMessage
}

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

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.

type ForwardingInfo

type ForwardingInfo struct {
	// Network is the target blockchain network that the HTLC will travel
	// over next.
	Network NetworkHop

	// NextHop is the channel ID of the next hop. The received HTLC should
	// be forwarded to this particular channel in order to continue the
	// end-to-end route.
	NextHop lnwire.ShortChannelID

	// AmountToForward is the amount of milli-satoshis that the receiving
	// node should forward to the next hop.
	AmountToForward lnwire.MilliSatoshi

	// OutgoingCTLV is the specified value of the CTLV timelock to be used
	// in the outgoing HTLC.
	OutgoingCTLV uint32
}

ForwardingInfo contains all the information that is necessary to forward and incoming HTLC to the next hop encoded within a valid HopIterator instance. Forwarding links are to use this information to authenticate the information received within the incoming HTLC, to ensure that the prior hop didn't tamper with the end-to-end routing information at all.

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 ForwardingPolicy

type ForwardingPolicy struct {
	// MinHTLC is the smallest HTLC that is to be forwarded. This is
	// set when a channel is first opened, and will be static for the
	// lifetime of the channel.
	MinHTLC lnwire.MilliSatoshi

	// BaseFee is the base fee, expressed in milli-satoshi that must be
	// paid for each incoming HTLC. This field, combined with FeeRate is
	// used to compute the required fee for a given HTLC.
	BaseFee lnwire.MilliSatoshi

	// FeeRate is the fee rate, expressed in milli-satoshi that must be
	// paid for each incoming HTLC. This field combined with BaseFee is
	// used to compute the required fee for a given HTLC.
	FeeRate lnwire.MilliSatoshi

	// TimeLockDelta is the absolute time-lock value, expressed in blocks,
	// that will be subtracted from an incoming HTLC's timelock value to
	// create the time-lock value for the forwarded outgoing HTLC. The
	// following constraint MUST hold for an HTLC to be forwarded:
	//
	//  * incomingHtlc.timeLock - timeLockDelta = fwdInfo.OutgoingCTLV
	//
	//    where fwdInfo is the forwarding information extracted from the
	//    per-hop payload of the incoming HTLC's onion packet.
	TimeLockDelta uint32
}

ForwardingPolicy describes the set of constraints that a given ChannelLink is to adhere to when forwarding HTLC's. For each incoming HTLC, this set of constraints will be consulted in order to ensure that adequate fees are paid, and our time-lock parameters are respected. In the event that an incoming HTLC violates any of these constraints, it is to be _rejected_ with the error possibly carrying along a ChannelUpdate message that includes the latest policy.

type HopIterator

type HopIterator interface {
	// ForwardingInstructions returns the set of fields that detail exactly
	// _how_ this hop should forward the HTLC to the next hop.
	// Additionally, the information encoded within the returned
	// ForwardingInfo is to be used by each hop to authenticate the
	// information given to it by the prior hop.
	ForwardingInstructions() ForwardingInfo

	// EncodeNextHop encodes the onion packet destined for the next hop
	// into the passed io.Writer.
	EncodeNextHop(w io.Writer) error

	// ExtractErrorEncrypter returns the ErrorEncrypter needed for this hop,
	// along with a failure code to signal if the decoding was successful.
	ExtractErrorEncrypter(ErrorEncrypterExtracter) (ErrorEncrypter,
		lnwire.FailCode)
}

HopIterator is an interface that abstracts away the routing information included in HTLC's which includes the entirety of the payment path of an HTLC. This interface provides two basic method which carry out: how to interpret the forwarding information encoded within the HTLC packet, and hop to encode the forwarding information for the _next_ hop.

type InvoiceDatabase

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

	// SettleInvoice attempts to mark an invoice corresponding to the
	// passed payment hash as fully settled.
	SettleInvoice(chainhash.Hash) error
}

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 LinkFailureError

type LinkFailureError struct {

	// ForceClose indicates whether we should force close the channel
	// because of this error.
	ForceClose 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.
	AckPacket(CircuitKey) error

	// 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

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

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

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 servers 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 NetworkHop

type NetworkHop uint8

NetworkHop indicates the blockchain network that is intended to be the next hop for a forwarded HTLC. The existence of this field within the ForwardingInfo struct enables the ability for HTLC to cross chain-boundaries at will.

const (
	// BitcoinHop denotes that an HTLC is to be forwarded along the Bitcoin
	// link with the specified short channel ID.
	BitcoinHop NetworkHop = iota

	// LitecoinHop denotes that an HTLC is to be forwarded along the
	// Litecoin link with the specified short channel ID.
	LitecoinHop
)

func (NetworkHop) String

func (c NetworkHop) String() string

String returns the string representation of the target NetworkHop.

type OnionProcessor

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

OnionProcessor is responsible for keeping all sphinx dependent parts inside and expose only decoding function. With such approach we give freedom for subsystems which wants to decode sphinx path to not be dependable from sphinx at all.

NOTE: The reason for keeping decoder separated from hop iterator is too maintain the hop iterator abstraction. Without it the structures which using the hop iterator should contain sphinx router which makes their creations in tests dependent from the sphinx internal parts.

func NewOnionProcessor

func NewOnionProcessor(router *sphinx.Router) *OnionProcessor

NewOnionProcessor creates new instance of decoder.

func (*OnionProcessor) DecodeHopIterator

func (p *OnionProcessor) DecodeHopIterator(r io.Reader, rHash []byte,
	incomingCltv uint32) (HopIterator, lnwire.FailCode)

DecodeHopIterator attempts to decode a valid sphinx packet from the passed io.Reader instance using the rHash as the associated data when checking the relevant MACs during the decoding process.

func (*OnionProcessor) DecodeHopIterators

func (p *OnionProcessor) DecodeHopIterators(id []byte,
	reqs []DecodeHopIteratorRequest) ([]DecodeHopIteratorResponse, error)

DecodeHopIterators performs batched decoding and validation of incoming sphinx packets. For the same `id`, this method will return the same iterators and failcodes upon subsequent invocations.

NOTE: In order for the responses to be valid, the caller must guarantee that the presented readers and rhashes *NEVER* deviate across invocations for the same id.

func (*OnionProcessor) ExtractErrorEncrypter

func (p *OnionProcessor) ExtractErrorEncrypter(ephemeralKey *btcec.PublicKey) (
	ErrorEncrypter, lnwire.FailCode)

ExtractErrorEncrypter takes an io.Reader which should contain the onion packet as original received by a forwarding node and creates an ErrorEncrypter instance using the derived shared secret. In the case that en error occurs, a lnwire failure code detailing the parsing failure will be returned.

func (*OnionProcessor) Start

func (p *OnionProcessor) Start() error

Start spins up the onion processor's sphinx router.

func (*OnionProcessor) Stop

func (p *OnionProcessor) Stop() error

Stop shutsdown the onion processor's sphinx router.

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 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 Peer

type Peer interface {
	// SendMessage sends message to remote peer. The second argument
	// denotes if the method should block until the message has been sent
	// to the remote peer.
	SendMessage(msg lnwire.Message, sync bool) error

	// WipeChannel removes the channel uniquely identified by its channel
	// point from all indexes associated with the peer.
	WipeChannel(*wire.OutPoint) error

	// PubKey returns the serialize public key of the source peer.
	PubKey() [33]byte
}

Peer is an interface which represents the remote lightning node inside our system.

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 SphinxErrorDecrypter

type SphinxErrorDecrypter struct {
	*sphinx.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 SphinxErrorEncrypter

type SphinxErrorEncrypter struct {
	*sphinx.OnionErrorEncrypter

	EphemeralKey *btcec.PublicKey
}

SphinxErrorEncrypter is a concrete implementation of both the ErrorEncrypter interface backed by an implementation of the Sphinx packet format. As a result, all errors handled are themselves wrapped in layers of onion encryption and must be treated as such accordingly.

func NewSphinxErrorEncrypter

func NewSphinxErrorEncrypter() *SphinxErrorEncrypter

NewSphinxErrorEncrypter initializes a blank sphinx error encrypter, that should be used to deserialize an encoded SphinxErrorEncrypter. Since the actual encrypter is not stored in plaintext while at rest, reconstructing the error encrypter requires:

  1. Decode: to deserialize the ephemeral public key.
  2. Reextract: to "unlock" the actual error encrypter using an active OnionProcessor.

func (*SphinxErrorEncrypter) Decode

func (s *SphinxErrorEncrypter) Decode(r io.Reader) error

Decode reconstructs the error encrypter's ephemeral public key from the provided io.Reader.

func (*SphinxErrorEncrypter) Encode

func (s *SphinxErrorEncrypter) Encode(w io.Writer) error

Encode serializes the error encrypter' ephemeral public key to the provided io.Writer.

func (*SphinxErrorEncrypter) EncryptFirstHop

func (s *SphinxErrorEncrypter) EncryptFirstHop(failure lnwire.FailureMessage) (lnwire.OpaqueReason, error)

EncryptFirstHop transforms a concrete failure message into an encrypted opaque failure reason. This method will be used at the source that the error occurs. It differs from BackwardObfuscate slightly, in that it computes a proper MAC over the error.

NOTE: Part of the ErrorEncrypter interface.

func (*SphinxErrorEncrypter) IntermediateEncrypt

func (s *SphinxErrorEncrypter) IntermediateEncrypt(reason lnwire.OpaqueReason) lnwire.OpaqueReason

IntermediateEncrypt wraps an already encrypted opaque reason error in an additional layer of onion encryption. This process repeats until the error arrives at the source of the payment. We re-encrypt the message on the backwards path to ensure that the error is indistinguishable from any other error seen.

NOTE: Part of the ErrorEncrypter interface.

func (*SphinxErrorEncrypter) Reextract

func (s *SphinxErrorEncrypter) Reextract(
	extract ErrorEncrypterExtracter) error

Reextract rederives the error encrypter from the currently held EphemeralKey. This intended to be used shortly after Decode, to fully initialize a SphinxErrorEncrypter.

func (*SphinxErrorEncrypter) Type

Type returns the identifier for a sphinx error encrypter.

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) (*Switch, error)

New creates the new instance of htlc switch.

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) 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 (s *Switch) CloseLink(chanPoint *wire.OutPoint, closeType ChannelCloseType,
	targetFeePerKw lnwallet.SatPerKWeight) (chan *lnrpc.CloseStatusUpdate,
	chan error)

CloseLink creates and sends the close channel command to the target link directing the specified closure type. If the closure type if CloseRegular, then the last parameter should be the ideal fee-per-kw that will be used as a starting point for close negotiation.

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(packets ...*htlcPacket) chan 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.

NOTE: This method guarantees that the returned err chan will eventually be closed. The receiver should read on the channel until receiving such a signal.

func (s *Switch) GetLink(chanID lnwire.ChannelID) (ChannelLink, 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) GetLinksByInterface

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

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

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) error

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

func (*Switch) SendHTLC

func (s *Switch) SendHTLC(nextNode [33]byte, htlc *lnwire.UpdateAddHTLC,
	deobfuscator ErrorDecrypter) ([sha256.Size]byte, error)

SendHTLC is used by other subsystems which aren't belong to htlc switch package in order to send the htlc update.

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(newPolicy ForwardingPolicy,
	targetChans ...wire.OutPoint) error

UpdateForwardingPolicies sends a message to the switch to update the forwarding policies for the set of target channels. If the set of targeted channels is nil, then the forwarding policies for all active channels with be updated.

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 updates the short chan ID for an existing channel. This is required in the case of a re-org and re-confirmation or a channel, or in the case that a link was added to the switch before its short chan ID was known.

type Ticker

type Ticker interface {
	Start() <-chan time.Time

	Stop()
}

Ticker is an interface used to wrap a time.Ticker in a struct, making mocking it easier.

type UnknownEncrypterType

type UnknownEncrypterType 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