@@ -1545,69 +1545,123 @@ func getEdgeUnifiers(source route.Vertex, hops []route.Vertex,
15451545// determines the amount that should be sent to fulfill min HTLC requirements.
15461546// The minimal sender amount can be searched for by activating useMinAmt.
15471547func senderAmtBackwardPass (unifiers []* edgeUnifier , useMinAmt bool ,
1548- runningAmt lnwire.MilliSatoshi ,
1548+ receiverAmt lnwire.MilliSatoshi ,
15491549 bandwidthHints bandwidthHints ) ([]* unifiedEdge , lnwire.MilliSatoshi ,
15501550 error ) {
15511551
1552+ if len (unifiers ) == 0 {
1553+ return nil , 0 , fmt .Errorf ("no unifiers provided" )
1554+ }
1555+
15521556 var unifiedEdges = make ([]* unifiedEdge , len (unifiers ))
15531557
1554- // Traverse hops backwards to accumulate fees in the running amounts.
1555- for i := len (unifiers ) - 1 ; i >= 0 ; i -- {
1556- localChan := i == 0
1557- edgeUnifier := unifiers [i ]
1558+ // We traverse the route backwards and handle the last hop separately.
1559+ edgeUnifier := unifiers [len (unifiers )- 1 ]
1560+
1561+ // incomingAmt tracks the amount that is forwarded on the edges of a
1562+ // route. The last hop only forwards the amount that the receiver should
1563+ // receive, as there are no fees paid to the last node.
1564+ incomingAmt := receiverAmt
1565+
1566+ // If using min amt, increase the amount if needed to fulfill min HTLC
1567+ // requirements.
1568+ if useMinAmt {
1569+ min := edgeUnifier .minAmt ()
1570+ if min > incomingAmt {
1571+ incomingAmt = min
1572+ }
1573+ }
15581574
1559- // If using min amt, increase amt if needed.
1575+ // Get an edge for the specific amount that we want to forward.
1576+ edge := edgeUnifier .getEdge (incomingAmt , bandwidthHints , 0 )
1577+ if edge == nil {
1578+ log .Errorf ("Cannot find policy with amt=%v " +
1579+ "for hop %v" , incomingAmt , len (unifiers )- 1 )
1580+
1581+ return nil , 0 , ErrNoChannel {position : len (unifiers ) - 1 }
1582+ }
1583+
1584+ unifiedEdges [len (unifiers )- 1 ] = edge
1585+
1586+ // Handle the rest of the route except the last hop.
1587+ for i := len (unifiers ) - 2 ; i >= 0 ; i -- {
1588+ edgeUnifier = unifiers [i ]
1589+
1590+ // If using min amt, increase the amount if needed to fulfill
1591+ // min HTLC requirements.
15601592 if useMinAmt {
15611593 min := edgeUnifier .minAmt ()
1562- if min > runningAmt {
1563- runningAmt = min
1594+ if min > incomingAmt {
1595+ incomingAmt = min
15641596 }
15651597 }
15661598
1567- // Get an edge for the specific amount that we want to forward.
1568- edge := edgeUnifier .getEdge (runningAmt , bandwidthHints , 0 )
1569- if edge == nil {
1570- log .Errorf ("Cannot find policy with amt=%v for hop %v" ,
1571- runningAmt , i )
1599+ // A --current hop-- B --next hop: incomingAmt-- C
1600+ // The outbound fee paid to the current end node B is based on
1601+ // the amount that the next hop forwards and B's policy for that
1602+ // hop.
1603+ outboundFee := unifiedEdges [i + 1 ].policy .ComputeFee (
1604+ incomingAmt ,
1605+ )
15721606
1573- return nil , 0 , ErrNoChannel {
1574- position : i ,
1575- }
1576- }
1607+ netAmount := incomingAmt + outboundFee
15771608
1578- // Add fee for this hop.
1579- if ! localChan {
1580- runningAmt += edge .policy .ComputeFee (runningAmt )
1609+ // We need to select an edge that can forward the requested
1610+ // amount.
1611+ edge = edgeUnifier .getEdge (
1612+ netAmount , bandwidthHints , outboundFee ,
1613+ )
1614+ if edge == nil {
1615+ return nil , 0 , ErrNoChannel {position : i }
15811616 }
15821617
1618+ fee := outboundFee
1619+
15831620 log .Tracef ("Select channel %v at position %v" ,
15841621 edge .policy .ChannelID , i )
15851622
1623+ // Finally, we update the amount that needs to flow into node B
1624+ // from A, which is the next hop's forwarding amount plus the
1625+ // fee for B: A --current hop: incomingAmt-- B --next hop-- C
1626+ incomingAmt += fee
1627+
15861628 unifiedEdges [i ] = edge
15871629 }
15881630
1589- return unifiedEdges , runningAmt , nil
1631+ return unifiedEdges , incomingAmt , nil
15901632}
15911633
15921634// receiverAmtForwardPass returns the amount that a receiver will receive after
15931635// deducting all fees from the sender amount.
15941636func receiverAmtForwardPass (runningAmt lnwire.MilliSatoshi ,
15951637 unifiedEdges []* unifiedEdge ) (lnwire.MilliSatoshi , error ) {
15961638
1639+ if len (unifiedEdges ) == 0 {
1640+ return 0 , fmt .Errorf ("no edges to forward through" )
1641+ }
1642+
1643+ inEdge := unifiedEdges [0 ]
1644+ if ! inEdge .amtInRange (runningAmt ) {
1645+ log .Errorf ("Amount %v not in range for hop index %v" ,
1646+ runningAmt , 0 )
1647+
1648+ return 0 , ErrNoChannel {position : 0 }
1649+ }
1650+
15971651 // Now that we arrived at the start of the route and found out the route
15981652 // total amount, we make a forward pass. Because the amount may have
15991653 // been increased in the backward pass, fees need to be recalculated and
16001654 // amount ranges re-checked.
1601- for i , edge := range unifiedEdges {
1602- if i > 0 {
1603- // Decrease the amount to send while going forward.
1604- runningAmt -= edge . policy . ComputeFeeFromIncoming (
1605- runningAmt ,
1606- )
1607- }
1655+ for i := 1 ; i < len ( unifiedEdges ); i ++ {
1656+ outEdge := unifiedEdges [ i ]
1657+
1658+ // Decrease the amount to send while going forward.
1659+ runningAmt -= outEdge . policy . ComputeFeeFromIncoming (
1660+ runningAmt ,
1661+ )
16081662
1609- if ! edge .amtInRange (runningAmt ) {
1610- log .Errorf ("Amount %v not in range for hop %v" ,
1663+ if ! outEdge .amtInRange (runningAmt ) {
1664+ log .Errorf ("Amount %v not in range for hop index %v" ,
16111665 runningAmt , i )
16121666
16131667 return 0 , ErrNoChannel {position : i }
0 commit comments