Skip to content

Commit 452db01

Browse files
committed
lnrpc+routing: convert amt pointer to fn.Option
1 parent 8b32e3e commit 452db01

File tree

3 files changed

+55
-54
lines changed

3 files changed

+55
-54
lines changed

lnrpc/routerrpc/router_server.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/btcsuite/btcd/wire"
1616
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
1717
"github.com/lightningnetwork/lnd/channeldb"
18+
"github.com/lightningnetwork/lnd/fn"
1819
"github.com/lightningnetwork/lnd/lnrpc"
1920
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
2021
"github.com/lightningnetwork/lnd/lntypes"
@@ -1411,10 +1412,10 @@ func (s *Server) BuildRoute(_ context.Context,
14111412
}
14121413

14131414
// Prepare BuildRoute call parameters from rpc request.
1414-
var amt *lnwire.MilliSatoshi
1415+
var amt fn.Option[lnwire.MilliSatoshi]
14151416
if req.AmtMsat != 0 {
14161417
rpcAmt := lnwire.MilliSatoshi(req.AmtMsat)
1417-
amt = &rpcAmt
1418+
amt = fn.Some(rpcAmt)
14181419
}
14191420

14201421
var outgoingChan *uint64

routing/router.go

Lines changed: 35 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1406,7 +1406,7 @@ func (e ErrNoChannel) Error() string {
14061406
// BuildRoute returns a fully specified route based on a list of pubkeys. If
14071407
// amount is nil, the minimum routable amount is used. To force a specific
14081408
// outgoing channel, use the outgoingChan parameter.
1409-
func (r *ChannelRouter) BuildRoute(amt *lnwire.MilliSatoshi,
1409+
func (r *ChannelRouter) BuildRoute(amt fn.Option[lnwire.MilliSatoshi],
14101410
hops []route.Vertex, outgoingChan *uint64,
14111411
finalCltvDelta int32, payAddr *[32]byte) (*route.Route, error) {
14121412

@@ -1439,43 +1439,36 @@ func (r *ChannelRouter) BuildRoute(amt *lnwire.MilliSatoshi,
14391439
return nil, err
14401440
}
14411441

1442-
// If no amount is specified, we need to build a route for the minimum
1443-
// amount that this route can carry.
1444-
useMinAmt := amt == nil
1445-
14461442
var (
14471443
receiverAmt lnwire.MilliSatoshi
1444+
senderAmt lnwire.MilliSatoshi
14481445
pathEdges []*unifiedEdge
14491446
)
14501447

1451-
if useMinAmt {
1452-
// For minimum amount routes, aim to deliver at least 1 msat to
1453-
// the destination. There are nodes in the wild that have a
1454-
// min_htlc channel policy of zero, which could lead to a zero
1455-
// amount payment being made.
1456-
var senderAmt lnwire.MilliSatoshi
1457-
pathEdges, senderAmt, err = senderAmtBackwardPass(
1458-
unifiers, useMinAmt, 1, bandwidthHints,
1459-
)
1460-
if err != nil {
1461-
return nil, err
1462-
}
1463-
1464-
receiverAmt, err = receiverAmtForwardPass(senderAmt, pathEdges)
1465-
if err != nil {
1466-
return nil, err
1467-
}
1468-
} else {
1469-
// If an amount is specified, we need to build a route that
1470-
// delivers exactly this amount to the final destination.
1471-
pathEdges, _, err = senderAmtBackwardPass(
1472-
unifiers, useMinAmt, *amt, bandwidthHints,
1473-
)
1474-
if err != nil {
1475-
return nil, err
1476-
}
1448+
// We determine the edges compatible with the requested amount, as well
1449+
// as the amount to send, which can be used to determine the final
1450+
// receiver amount, if a minimal amount was requested.
1451+
pathEdges, senderAmt, err = senderAmtBackwardPass(
1452+
unifiers, amt, bandwidthHints,
1453+
)
1454+
if err != nil {
1455+
return nil, err
1456+
}
14771457

1478-
receiverAmt = *amt
1458+
// For the minimal amount search, we need to do a forward pass to find a
1459+
// larger receiver amount due to possible min HTLC bumps, otherwise we
1460+
// just use the requested amount.
1461+
receiverAmt, err = fn.ElimOption(
1462+
amt,
1463+
func() fn.Result[lnwire.MilliSatoshi] {
1464+
return fn.NewResult(
1465+
receiverAmtForwardPass(senderAmt, pathEdges),
1466+
)
1467+
},
1468+
fn.Ok[lnwire.MilliSatoshi],
1469+
).Unpack()
1470+
if err != nil {
1471+
return nil, err
14791472
}
14801473

14811474
// Fetch the current block height outside the routing transaction, to
@@ -1545,9 +1538,9 @@ func getEdgeUnifiers(source route.Vertex, hops []route.Vertex,
15451538

15461539
// senderAmtBackwardPass returns a list of unified edges for the given route and
15471540
// determines the amount that should be sent to fulfill min HTLC requirements.
1548-
// The minimal sender amount can be searched for by activating useMinAmt.
1549-
func senderAmtBackwardPass(unifiers []*edgeUnifier, useMinAmt bool,
1550-
receiverAmt lnwire.MilliSatoshi,
1541+
// The minimal sender amount can be searched for by using amt=None.
1542+
func senderAmtBackwardPass(unifiers []*edgeUnifier,
1543+
amt fn.Option[lnwire.MilliSatoshi],
15511544
bandwidthHints bandwidthHints) ([]*unifiedEdge, lnwire.MilliSatoshi,
15521545
error) {
15531546

@@ -1563,11 +1556,15 @@ func senderAmtBackwardPass(unifiers []*edgeUnifier, useMinAmt bool,
15631556
// incomingAmt tracks the amount that is forwarded on the edges of a
15641557
// route. The last hop only forwards the amount that the receiver should
15651558
// receive, as there are no fees paid to the last node.
1566-
incomingAmt := receiverAmt
1559+
// For minimum amount routes, aim to deliver at least 1 msat to
1560+
// the destination. There are nodes in the wild that have a
1561+
// min_htlc channel policy of zero, which could lead to a zero
1562+
// amount payment being made.
1563+
incomingAmt := amt.UnwrapOr(1)
15671564

15681565
// If using min amt, increase the amount if needed to fulfill min HTLC
15691566
// requirements.
1570-
if useMinAmt {
1567+
if amt.IsNone() {
15711568
min := edgeUnifier.minAmt()
15721569
if min > incomingAmt {
15731570
incomingAmt = min
@@ -1591,7 +1588,7 @@ func senderAmtBackwardPass(unifiers []*edgeUnifier, useMinAmt bool,
15911588

15921589
// If using min amt, increase the amount if needed to fulfill
15931590
// min HTLC requirements.
1594-
if useMinAmt {
1591+
if amt.IsNone() {
15951592
min := edgeUnifier.minAmt()
15961593
if min > incomingAmt {
15971594
incomingAmt = min

routing/router_test.go

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"github.com/lightningnetwork/lnd/channeldb"
2525
"github.com/lightningnetwork/lnd/channeldb/models"
2626
"github.com/lightningnetwork/lnd/clock"
27+
"github.com/lightningnetwork/lnd/fn"
2728
"github.com/lightningnetwork/lnd/graph"
2829
"github.com/lightningnetwork/lnd/htlcswitch"
2930
"github.com/lightningnetwork/lnd/input"
@@ -1641,14 +1642,16 @@ func TestBuildRoute(t *testing.T) {
16411642
_, err = rand.Read(payAddr[:])
16421643
require.NoError(t, err)
16431644

1645+
noAmt := fn.None[lnwire.MilliSatoshi]()
1646+
16441647
// Test that we can't build a route when no hops are given.
16451648
hops = []route.Vertex{}
1646-
_, err = ctx.router.BuildRoute(nil, hops, nil, 40, nil)
1649+
_, err = ctx.router.BuildRoute(noAmt, hops, nil, 40, nil)
16471650
require.Error(t, err)
16481651

16491652
// Create hop list for an unknown destination.
16501653
hops := []route.Vertex{ctx.aliases["b"], ctx.aliases["y"]}
1651-
_, err = ctx.router.BuildRoute(nil, hops, nil, 40, &payAddr)
1654+
_, err = ctx.router.BuildRoute(noAmt, hops, nil, 40, &payAddr)
16521655
noChanErr := ErrNoChannel{}
16531656
require.ErrorAs(t, err, &noChanErr)
16541657
require.Equal(t, 1, noChanErr.position)
@@ -1658,7 +1661,7 @@ func TestBuildRoute(t *testing.T) {
16581661
amt := lnwire.NewMSatFromSatoshis(100)
16591662

16601663
// Build the route for the given amount.
1661-
rt, err := ctx.router.BuildRoute(&amt, hops, nil, 40, &payAddr)
1664+
rt, err := ctx.router.BuildRoute(fn.Some(amt), hops, nil, 40, &payAddr)
16621665
require.NoError(t, err)
16631666

16641667
// Check that we get the expected route back. The total amount should be
@@ -1668,7 +1671,7 @@ func TestBuildRoute(t *testing.T) {
16681671
require.Equal(t, lnwire.MilliSatoshi(106000), rt.TotalAmount)
16691672

16701673
// Build the route for the minimum amount.
1671-
rt, err = ctx.router.BuildRoute(nil, hops, nil, 40, &payAddr)
1674+
rt, err = ctx.router.BuildRoute(noAmt, hops, nil, 40, &payAddr)
16721675
require.NoError(t, err)
16731676

16741677
// Check that we get the expected route back. The minimum that we can
@@ -1684,7 +1687,7 @@ func TestBuildRoute(t *testing.T) {
16841687
// Test a route that contains incompatible channel htlc constraints.
16851688
// There is no amount that can pass through both channel 5 and 4.
16861689
hops = []route.Vertex{ctx.aliases["e"], ctx.aliases["c"]}
1687-
_, err = ctx.router.BuildRoute(nil, hops, nil, 40, nil)
1690+
_, err = ctx.router.BuildRoute(noAmt, hops, nil, 40, nil)
16881691
require.Error(t, err)
16891692
noChanErr = ErrNoChannel{}
16901693
require.ErrorAs(t, err, &noChanErr)
@@ -1702,7 +1705,7 @@ func TestBuildRoute(t *testing.T) {
17021705
// amount that could be delivered to the receiver of 21819 msat, using
17031706
// policy of channel 3.
17041707
hops = []route.Vertex{ctx.aliases["b"], ctx.aliases["z"]}
1705-
rt, err = ctx.router.BuildRoute(nil, hops, nil, 40, &payAddr)
1708+
rt, err = ctx.router.BuildRoute(noAmt, hops, nil, 40, &payAddr)
17061709
require.NoError(t, err)
17071710
checkHops(rt, []uint64{1, 8}, payAddr)
17081711
require.Equal(t, lnwire.MilliSatoshi(21200), rt.TotalAmount)
@@ -1714,7 +1717,7 @@ func TestBuildRoute(t *testing.T) {
17141717
// We get 106000 - 1000 (base in) - 0.001 * 106000 (rate in) = 104894.
17151718
hops = []route.Vertex{ctx.aliases["d"], ctx.aliases["f"]}
17161719
amt = lnwire.NewMSatFromSatoshis(100)
1717-
rt, err = ctx.router.BuildRoute(&amt, hops, nil, 40, &payAddr)
1720+
rt, err = ctx.router.BuildRoute(fn.Some(amt), hops, nil, 40, &payAddr)
17181721
require.NoError(t, err)
17191722
checkHops(rt, []uint64{9, 10}, payAddr)
17201723
require.EqualValues(t, 104894, rt.TotalAmount)
@@ -1728,7 +1731,7 @@ func TestBuildRoute(t *testing.T) {
17281731
// of 20179 msat, which results in underpayment of 1 msat in fee. There
17291732
// is a third pass through newRoute in which this gets corrected to end
17301733
hops = []route.Vertex{ctx.aliases["d"], ctx.aliases["f"]}
1731-
rt, err = ctx.router.BuildRoute(nil, hops, nil, 40, &payAddr)
1734+
rt, err = ctx.router.BuildRoute(noAmt, hops, nil, 40, &payAddr)
17321735
require.NoError(t, err)
17331736
checkHops(rt, []uint64{9, 10}, payAddr)
17341737
require.EqualValues(t, 20180, rt.TotalAmount, "%v", rt.TotalAmount)
@@ -1919,20 +1922,20 @@ func TestSenderAmtBackwardPass(t *testing.T) {
19191922
// A search for an amount that is below the minimum HTLC amount should
19201923
// fail.
19211924
_, _, err := senderAmtBackwardPass(
1922-
edgeUnifiers, false, minHTLC-1, &bandwidthHints,
1925+
edgeUnifiers, fn.Some(minHTLC-1), &bandwidthHints,
19231926
)
19241927
require.Error(t, err)
19251928

19261929
// Do a min amount search.
1927-
unifiedEdges, senderAmount, err := senderAmtBackwardPass(
1928-
edgeUnifiers, true, 1, &bandwidthHints,
1930+
_, senderAmount, err := senderAmtBackwardPass(
1931+
edgeUnifiers, fn.None[lnwire.MilliSatoshi](), &bandwidthHints,
19291932
)
19301933
require.NoError(t, err)
19311934
require.Equal(t, minHTLC+333+222+222+111, senderAmount)
19321935

19331936
// Do a search for a specific amount.
1934-
unifiedEdges, senderAmount, err = senderAmtBackwardPass(
1935-
edgeUnifiers, false, testReceiverAmt, &bandwidthHints,
1937+
unifiedEdges, senderAmount, err := senderAmtBackwardPass(
1938+
edgeUnifiers, fn.Some(testReceiverAmt), &bandwidthHints,
19361939
)
19371940
require.NoError(t, err)
19381941
require.Equal(t, testReceiverAmt+333+222+222+111, senderAmount)
@@ -1961,7 +1964,7 @@ func TestSenderAmtBackwardPass(t *testing.T) {
19611964
}
19621965

19631966
unifiedEdges, senderAmount, err = senderAmtBackwardPass(
1964-
edgeUnifiers, false, testReceiverAmt, &bandwidthHints,
1967+
edgeUnifiers, fn.Some(testReceiverAmt), &bandwidthHints,
19651968
)
19661969
require.NoError(t, err)
19671970

0 commit comments

Comments
 (0)