hop

package
v0.18.0-beta.rc1 Latest Latest
Warning

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

Go to latest
Published: Apr 27, 2024 License: MIT Imports: 12 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

	// EncrypterTypeIntroduction is used to identify a sphinx onion error
	// encrypter where we are the introduction node in a blinded route. It
	// has the same functionality as EncrypterTypeSphinx, but is used to
	// mark our special-case error handling.
	EncrypterTypeIntroduction = 3

	// EncrypterTypeRelaying is used to identify a sphinx onion error
	// encryper where we are a relaying node in a blinded route. It has
	// the same functionality as a EncrypterTypeSphinx, but is used to mark
	// our special-case error handling.
	EncrypterTypeRelaying = 4
)

Variables

View Source
var (
	// ErrDecodeFailed is returned when we can't decode blinded data.
	ErrDecodeFailed = errors.New("could not decode blinded data")

	// ErrNoBlindingPoint is returned when we have not provided a blinding
	// point for a validated payload with encrypted data set.
	ErrNoBlindingPoint = errors.New("no blinding point set for validated " +
		"blinded hop")
)
View Source
var (
	// Exit is a special "hop" denoting that an incoming HTLC is meant to
	// pay finally to the receiving node.
	Exit lnwire.ShortChannelID

	// Source is a sentinel "hop" denoting that an incoming HTLC is
	// initiated by our own switch.
	Source lnwire.ShortChannelID
)

Functions

func NewCustomRecords

func NewCustomRecords(parsedTypes tlv.TypeMap) record.CustomSet

NewCustomRecords filters the types parsed from the tlv stream for custom records.

func UseLogger

func UseLogger(logger btclog.Logger)

UseLogger uses a specified Logger to output package logging info. This function is called from the parent package htlcswitch logger initialization.

func ValidateBlindedRouteData

func ValidateBlindedRouteData(blindedData *record.BlindedRouteData,
	incomingAmount lnwire.MilliSatoshi, incomingTimelock uint32) error

ValidateBlindedRouteData performs the additional validation that is required for payments that rely on data provided in an encrypted blob to be forwarded. We enforce the blinded route's maximum expiry height so that the route "expires" and a malicious party does not have endless opportunity to probe the blinded route and compare it to updated channel policies in the network.

Note that this function only validates blinded route data for forwarding nodes, as LND does not yet support receiving via a blinded route (which has different validation rules).

func ValidateParsedPayloadTypes

func ValidateParsedPayloadTypes(parsedTypes tlv.TypeMap,
	isFinalHop, updateAddBlinding bool) error

ValidateParsedPayloadTypes checks the types parsed from a hop payload to ensure that the proper fields are either included or omitted. The finalHop boolean should be true if the payload was parsed for an exit hop. The requirements for this method are described in BOLT 04.

func ValidatePayloadWithBlinded

func ValidatePayloadWithBlinded(isFinalHop bool,
	payloadParsed map[tlv.Type][]byte) error

ValidatePayloadWithBlinded validates a payload against the contents of its encrypted data blob.

func ValidateTLVPayload

func ValidateTLVPayload(parsedTypes map[tlv.Type][]byte,
	finalHop bool, updateAddBlinding bool) error

ValidateTLVPayload validates the TLV fields that were included in a TLV payload.

Types

type BlindingKit

type BlindingKit struct {
	// Processor provides the low-level cryptographic operations to
	// handle an encrypted blob of data in a blinded forward.
	Processor BlindingProcessor

	// UpdateAddBlinding holds a blinding point that was passed to the
	// node via update_add_htlc's TLVs.
	UpdateAddBlinding lnwire.BlindingPointRecord

	// IncomingCltv is the expiry of the incoming HTLC.
	IncomingCltv uint32

	// IncomingAmount is the amount of the incoming HTLC.
	IncomingAmount lnwire.MilliSatoshi
}

BlindingKit contains the components required to extract forwarding information for hops in a blinded route.

func (*BlindingKit) DecryptAndValidateFwdInfo

func (b *BlindingKit) DecryptAndValidateFwdInfo(payload *Payload,
	isFinalHop bool, payloadParsed map[tlv.Type][]byte) (
	*ForwardingInfo, error)

DecryptAndValidateFwdInfo performs all operations required to decrypt and validate a blinded route.

type BlindingProcessor

type BlindingProcessor interface {
	// DecryptBlindedHopData decrypts a blinded blob of data using the
	// ephemeral key provided.
	DecryptBlindedHopData(ephemPub *btcec.PublicKey,
		encryptedData []byte) ([]byte, error)

	// NextEphemeral returns the next hop's ephemeral key, calculated
	// from the current ephemeral key provided.
	NextEphemeral(*btcec.PublicKey) (*btcec.PublicKey, error)
}

BlindingProcessor is an interface that provides the cryptographic operations required for processing blinded hops.

This interface is extracted to allow more granular testing of blinded forwarding calculations.

type DecodeHopIteratorRequest

type DecodeHopIteratorRequest struct {
	OnionReader    io.Reader
	RHash          []byte
	IncomingCltv   uint32
	IncomingAmount lnwire.MilliSatoshi
	BlindingPoint  lnwire.BlindingPointRecord
}

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 Iterator
	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.

func (EncrypterType) IsBlinded

func (e EncrypterType) IsBlinded() bool

IsBlinded returns a boolean indicating whether the error encrypter belongs to a blinded route.

type ErrInvalidPayload

type ErrInvalidPayload struct {
	// Type the record's type that cause the violation.
	Type tlv.Type

	// Violation is an enum indicating the type of violation detected in
	// processing Type.
	Violation PayloadViolation

	// FinalHop if true, indicates that the violation is for the final hop
	// in the route (identified by next hop id), otherwise the violation is
	// for an intermediate hop.
	FinalHop bool
}

ErrInvalidPayload is an error returned when a parsed onion payload either included or omitted incorrect records for a particular hop type.

func (ErrInvalidPayload) Error

func (e ErrInvalidPayload) Error() string

Error returns a human-readable description of the invalid payload 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)

	// EncryptMalformedError is similar to EncryptFirstHop (it adds the
	// MAC), but it accepts an opaque failure reason rather than a failure
	// message. This method is used when we receive an
	// UpdateFailMalformedHTLC from the remote peer and then need to
	// convert that into a proper error from only the raw bytes.
	EncryptMalformedError(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.
	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.

type ErrorEncrypterExtracter

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

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

type ForwardingInfo

type ForwardingInfo struct {
	// 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

	// NextBlinding is an optional blinding point to be passed to the next
	// node in UpdateAddHtlc. This field is set if the htlc is part of a
	// blinded route.
	NextBlinding lnwire.BlindingPointRecord
}

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 IntroductionErrorEncrypter

type IntroductionErrorEncrypter struct {
	// ErrorEncrypter is the underlying error encrypter, embedded
	// directly in the struct so that we don't have to re-implement the
	// ErrorEncrypter interface.
	ErrorEncrypter
}

IntroductionErrorEncrypter is a wrapper type on SphinxErrorEncrypter which is used to signal that we have special HTLC error handling for this hop.

func NewIntroductionErrorEncrypter

func NewIntroductionErrorEncrypter() *IntroductionErrorEncrypter

NewIntroductionErrorEncrypter returns a blank IntroductionErrorEncrypter.

func (*IntroductionErrorEncrypter) Reextract

Reextract rederives the error encrypter from the currently held EphemeralKey, relying on the logic in the underlying SphinxErrorEncrypter.

func (*IntroductionErrorEncrypter) Type

Type returns the identifier for an introduction error encrypter.

type Iterator

type Iterator interface {
	// HopPayload 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. The payload will also contain any additional TLV fields provided
	// by the sender. The role that this hop plays in the context of
	// route blinding (regular, introduction or relaying) is returned
	// whenever the payload is successfully parsed, even if we subsequently
	// face a validation error.
	HopPayload() (*Payload, RouteRole, error)

	// 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(extractor ErrorEncrypterExtracter,
		introductionNode bool) (ErrorEncrypter, lnwire.FailCode)
}

Iterator 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 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) 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) ReconstructHopIterator

func (p *OnionProcessor) ReconstructHopIterator(r io.Reader, rHash []byte,
	blindingInfo ReconstructBlindingInfo) (Iterator, error)

ReconstructHopIterator 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) 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 Payload

type Payload struct {
	// FwdInfo holds the basic parameters required for HTLC forwarding, e.g.
	// amount, cltv, and next hop.
	FwdInfo ForwardingInfo

	// MPP holds the info provided in an option_mpp record when parsed from
	// a TLV onion payload.
	MPP *record.MPP

	// AMP holds the info provided in an option_amp record when parsed from
	// a TLV onion payload.
	AMP *record.AMP
	// contains filtered or unexported fields
}

Payload encapsulates all information delivered to a hop in an onion payload. A Hop can represent either a TLV or legacy payload. The primary forwarding instruction can be accessed via ForwardingInfo, and additional records can be accessed by other member functions.

func NewLegacyPayload

func NewLegacyPayload(f *sphinx.HopData) *Payload

NewLegacyPayload builds a Payload from the amount, cltv, and next hop parameters provided by leegacy onion payloads.

func ParseTLVPayload

func ParseTLVPayload(r io.Reader) (*Payload, map[tlv.Type][]byte, error)

ParseTLVPayload builds a new Hop from the passed io.Reader and returns a map of all the types that were found in the payload. This function does not perform validation of TLV types included in the payload.

func (*Payload) AMPRecord

func (h *Payload) AMPRecord() *record.AMP

AMPRecord returns the record corresponding with option_amp parsed from the onion payload.

func (*Payload) BlindingPoint

func (h *Payload) BlindingPoint() *btcec.PublicKey

BlindingPoint returns the route blinding point parsed from the onion payload.

func (*Payload) CustomRecords

func (h *Payload) CustomRecords() record.CustomSet

CustomRecords returns the custom tlv type records that were parsed from the payload.

func (*Payload) EncryptedData

func (h *Payload) EncryptedData() []byte

EncryptedData returns the route blinding encrypted data parsed from the onion payload.

func (*Payload) ForwardingInfo

func (h *Payload) ForwardingInfo() ForwardingInfo

ForwardingInfo returns the basic parameters required for HTLC forwarding, e.g. amount, cltv, and next hop.

func (*Payload) Metadata

func (h *Payload) Metadata() []byte

Metadata returns the additional data that is sent along with the payment to the payee.

func (*Payload) MultiPath

func (h *Payload) MultiPath() *record.MPP

MultiPath returns the record corresponding the option_mpp parsed from the onion payload.

func (*Payload) TotalAmtMsat

func (h *Payload) TotalAmtMsat() lnwire.MilliSatoshi

TotalAmtMsat returns the total amount sent to the final hop, as set by the payee.

type PayloadViolation

type PayloadViolation byte

PayloadViolation is an enum encapsulating the possible invalid payload violations that can occur when processing or validating a payload.

const (
	// OmittedViolation indicates that a type was expected to be found the
	// payload but was absent.
	OmittedViolation PayloadViolation = iota

	// IncludedViolation indicates that a type was expected to be omitted
	// from the payload but was present.
	IncludedViolation

	// RequiredViolation indicates that an unknown even type was found in
	// the payload that we could not process.
	RequiredViolation

	// InsufficientViolation indicates that the provided type does
	// not satisfy constraints.
	InsufficientViolation
)

func (PayloadViolation) String

func (v PayloadViolation) String() string

String returns a human-readable description of the violation as a verb.

type ReconstructBlindingInfo

type ReconstructBlindingInfo struct {
	// BlindingKey is the blinding point set in UpdateAddHTLC.
	BlindingKey lnwire.BlindingPointRecord

	// IncomingAmt is the amount for the incoming HTLC.
	IncomingAmt lnwire.MilliSatoshi

	// IncomingExpiry is the expiry height of the incoming HTLC.
	IncomingExpiry uint32
}

ReconstructBlindingInfo contains the information required to reconstruct a blinded onion.

type RelayingErrorEncrypter

type RelayingErrorEncrypter struct {
	ErrorEncrypter
}

RelayingErrorEncrypter is a wrapper type on SphinxErrorEncrypter which is used to signal that we have special HTLC error handling for this hop.

func NewRelayingErrorEncrypter

func NewRelayingErrorEncrypter() *RelayingErrorEncrypter

NewRelayingErrorEncrypter returns a blank RelayingErrorEncrypter with an underlying SphinxErrorEncrypter.

func (*RelayingErrorEncrypter) Reextract

func (r *RelayingErrorEncrypter) Reextract(
	extract ErrorEncrypterExtracter) error

Reextract rederives the error encrypter from the currently held EphemeralKey, relying on the logic in the underlying SphinxErrorEncrypter.

func (*RelayingErrorEncrypter) Type

Type returns the identifier for a relaying error encrypter.

type RouteRole

type RouteRole uint8

RouteRole represents the different types of roles a node can have as a recipient of a HTLC.

const (
	// RouteRoleCleartext represents a regular route hop.
	RouteRoleCleartext RouteRole = iota

	// RouteRoleIntroduction represents an introduction node in a blinded
	// path, characterized by a blinding point in the onion payload.
	RouteRoleIntroduction

	// RouteRoleRelaying represents a relaying node in a blinded path,
	// characterized by a blinding point in update_add_htlc.
	RouteRoleRelaying
)

func NewRouteRole

func NewRouteRole(updateAddBlinding, payloadBlinding bool) RouteRole

NewRouteRole returns the role we're playing in a route depending on the blinding points set (or not). If we are in the situation where we received blinding points in both the update add message and the payload:

  • We must have had a valid update add blinding point, because we were able to decrypt our onion to get the payload blinding point.
  • We return a relaying node role, because an introduction node (by definition) does not receive a blinding point in update add.
  • We assume the sending node to be buggy (including a payload blinding where it shouldn't), and rely on validation elsewhere to handle this.

func (RouteRole) String

func (h RouteRole) String() string

String representation of a role in a route.

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

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

EncryptMalformedError is similar to EncryptFirstHop (it adds the MAC), but it accepts an opaque failure reason rather than a failure message. This method is used when we receive an UpdateFailMalformedHTLC from the remote peer and then need to convert that into an proper error from only the raw bytes.

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.

Jump to

Keyboard shortcuts

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