@@ -11,6 +11,7 @@ import (
1111 sphinx "github.com/lightningnetwork/lightning-onion"
1212 "github.com/lightningnetwork/lnd/channeldb"
1313 "github.com/lightningnetwork/lnd/feature"
14+ "github.com/lightningnetwork/lnd/htlcswitch/hop"
1415 "github.com/lightningnetwork/lnd/lnwire"
1516 "github.com/lightningnetwork/lnd/record"
1617 "github.com/lightningnetwork/lnd/routing/route"
@@ -105,6 +106,36 @@ type finalHopParams struct {
105106 metadata []byte
106107}
107108
109+ // useAttrErrors returns true if the path can use attributable errors.
110+ func useAttrErrors (pathEdges []* channeldb.CachedEdgePolicy ) bool {
111+ // Use legacy errors if the route length exceeds the maximum number of
112+ // hops for attributable errors.
113+ if len (pathEdges ) > hop .AttrErrorStruct .HopCount () {
114+ return false
115+ }
116+
117+ // Every node along the path must signal support for attributable
118+ // errors.
119+ for _ , edge := range pathEdges {
120+ // Get the node features.
121+ toFeat := edge .ToNodeFeatures
122+
123+ // If there are no features known, assume the node cannot handle
124+ // attributable errors.
125+ if toFeat == nil {
126+ return false
127+ }
128+
129+ // If the node does not signal support for attributable errors,
130+ // do not use them.
131+ if ! toFeat .HasFeature (lnwire .AttributableErrorsOptional ) {
132+ return false
133+ }
134+ }
135+
136+ return true
137+ }
138+
108139// newRoute constructs a route using the provided path and final hop constraints.
109140// Any destination specific fields from the final hop params will be attached
110141// assuming the destination's feature vector signals support, otherwise this
@@ -117,7 +148,7 @@ type finalHopParams struct {
117148// dependencies.
118149func newRoute (sourceVertex route.Vertex ,
119150 pathEdges []* channeldb.CachedEdgePolicy , currentHeight uint32 ,
120- finalHop finalHopParams ) (* route.Route , error ) {
151+ finalHop finalHopParams , attrErrors bool ) (* route.Route , error ) {
121152
122153 var (
123154 hops []* route.Hop
@@ -134,6 +165,9 @@ func newRoute(sourceVertex route.Vertex,
134165 nextIncomingAmount lnwire.MilliSatoshi
135166 )
136167
168+ // Use attributable errors if enabled and supported by the route.
169+ attributableErrors := attrErrors && useAttrErrors (pathEdges )
170+
137171 pathLength := len (pathEdges )
138172 for i := pathLength - 1 ; i >= 0 ; i -- {
139173 // Now we'll start to calculate the items within the per-hop
@@ -250,6 +284,7 @@ func newRoute(sourceVertex route.Vertex,
250284 CustomRecords : customRecords ,
251285 MPP : mpp ,
252286 Metadata : metadata ,
287+ AttrError : attributableErrors ,
253288 }
254289
255290 hops = append ([]* route.Hop {currentHop }, hops ... )
@@ -371,6 +406,10 @@ type PathFindingConfig struct {
371406 // MinProbability defines the minimum success probability of the
372407 // returned route.
373408 MinProbability float64
409+
410+ // AttrErrors indicates whether we should use the new attributable
411+ // errors if the nodes on the route allow it.
412+ AttrErrors bool
374413}
375414
376415// getOutgoingBalance returns the maximum available balance in any of the
0 commit comments