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