lnd/routing/additional_edge.go
ziggie 9d3c0d9e3a
routing: add new interface AdditionalEdge.
A new interface AdditionalEdge is introduced which allows us to
enhance the CachedEdgePolicy with additional information. We
currently only need a PayloadSize function which is then used to
determine the exact payload size when building a route to adhere
to the sphinx package size limit (BOLT04).
2024-02-01 17:37:43 +00:00

108 lines
3.5 KiB
Go

package routing
import (
"errors"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/lightningnetwork/lnd/channeldb/models"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/routing/route"
)
var (
// ErrNoPayLoadSizeFunc is returned when no payload size function is
// definied.
ErrNoPayLoadSizeFunc = errors.New("no payloadSizeFunc defined for " +
"additional edge")
)
// AdditionalEdge is an interface which specifies additional edges which can
// be appended to an existing route. Compared to normal edges of a route they
// provide an explicit payload size function and are introduced because blinded
// paths differ in their payload structure.
type AdditionalEdge interface {
// IntermediatePayloadSize returns the size of the payload for the
// additional edge when being an intermediate hop in a route NOT the
// final hop.
IntermediatePayloadSize(amount lnwire.MilliSatoshi, expiry uint32,
legacy bool, channelID uint64) uint64
// EdgePolicy returns the policy of the additional edge.
EdgePolicy() *models.CachedEdgePolicy
}
// PayloadSizeFunc defines the interface for the payload size function.
type PayloadSizeFunc func(amount lnwire.MilliSatoshi, expiry uint32,
legacy bool, channelID uint64) uint64
// PrivateEdge implements the AdditionalEdge interface. As the name implies it
// is used for private route hints that the receiver adds for example to an
// invoice.
type PrivateEdge struct {
policy *models.CachedEdgePolicy
}
// EdgePolicy return the policy of the PrivateEdge.
func (p *PrivateEdge) EdgePolicy() *models.CachedEdgePolicy {
return p.policy
}
// IntermediatePayloadSize returns the sphinx payload size defined in BOLT04 if
// this edge were to be included in a route.
func (p *PrivateEdge) IntermediatePayloadSize(amount lnwire.MilliSatoshi,
expiry uint32, legacy bool, channelID uint64) uint64 {
hop := route.Hop{
AmtToForward: amount,
OutgoingTimeLock: expiry,
LegacyPayload: legacy,
}
return hop.PayloadSize(channelID)
}
// BlindedEdge implements the AdditionalEdge interface. Blinded hops are viewed
// as additional edges because they are appened at the end of a normal route.
type BlindedEdge struct {
policy *models.CachedEdgePolicy
cipherText []byte
blindingPoint *btcec.PublicKey
}
// EdgePolicy return the policy of the BlindedEdge.
func (b *BlindedEdge) EdgePolicy() *models.CachedEdgePolicy {
return b.policy
}
// IntermediatePayloadSize returns the sphinx payload size defined in BOLT04 if
// this edge were to be included in a route.
func (b *BlindedEdge) IntermediatePayloadSize(_ lnwire.MilliSatoshi, _ uint32,
_ bool, _ uint64) uint64 {
hop := route.Hop{
BlindingPoint: b.blindingPoint,
LegacyPayload: false,
EncryptedData: b.cipherText,
}
// For blinded paths the next chanID is in the encrypted data tlv.
return hop.PayloadSize(0)
}
// Compile-time constraints to ensure the PrivateEdge and the BlindedEdge
// implement the AdditionalEdge interface.
var _ AdditionalEdge = (*PrivateEdge)(nil)
var _ AdditionalEdge = (*BlindedEdge)(nil)
// defaultHopPayloadSize is the default payload size of a normal (not-blinded)
// hop in the route.
func defaultHopPayloadSize(amount lnwire.MilliSatoshi, expiry uint32,
legacy bool, channelID uint64) uint64 {
// The payload size of a cleartext intermediate hop is equal to the
// payload size of a private edge therefore we reuse its size function.
edge := PrivateEdge{}
return edge.IntermediatePayloadSize(amount, expiry, legacy, channelID)
}