Repository: lightningnetwork/lnd
Pull request #4209 (2020-04-20 07:45:17)

cert: define ExtendedKeyUsage as required by macOS 10.15/iOS 13.
Fixes  #4201.

It seems macOS 10.15 and iOS 13 [have new requirements for TLS certificates](https://support.apple.com/en-us/HT210176) that also apply to self-signed certs. If these requirements aren't met, the certificate is rejected, even if the self-signed CA is added to the list of trusted authorities (or when adding an "exception for this certificate" in a browser).

This PR adds the required

> TLS server certificates must contain an ExtendedKeyUsage (EKU) extension containing the id-kp-serverAuth OID.

to the self-signed certificates.

NOTE: After merging this PR, we must tag the `cert` submodule with a new version!


Patch:
diff --git a/cert/selfsigned.go b/cert/selfsigned.go
index f67e8cd8a..244d64b79 100644
--- a/cert/selfsigned.go
+++ b/cert/selfsigned.go
@@ -228,6 +228,7 @@ func GenCertPair(org, certFile, keyFile string, tlsExtraIPs,
 
 		KeyUsage: x509.KeyUsageKeyEncipherment |
 			x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
+		ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
 		IsCA:                  true, // so can sign self.
 		BasicConstraintsValid: true,
 
diff --git a/lnrpc/rpc.pb.go b/lnrpc/rpc.pb.go
index 10f9a7cde..28195cd61 100644
--- a/lnrpc/rpc.pb.go
+++ b/lnrpc/rpc.pb.go
@@ -7161,7 +7161,7 @@ type Hop struct {
 	//this field MUST be set to true for them to be encoded properly.
 	TlvPayload bool `protobuf:"varint,9,opt,name=tlv_payload,json=tlvPayload,proto3" json:"tlv_payload,omitempty"`
 	//*
-	//An optional TLV record that signals the use of an MPP payment. If present,
+	//An optional TLV record tha singals the use of an MPP payment. If present,
 	//the receiver will enforce that that the same mpp_record is included in the
 	//final hop payload of all non-zero payments in the HTLC set. If empty, a
 	//regular single-shot payment is or was attempted.
diff --git a/lnrpc/rpc.proto b/lnrpc/rpc.proto
index 1317b9640..fdfd1857f 100644
--- a/lnrpc/rpc.proto
+++ b/lnrpc/rpc.proto
@@ -2458,7 +2458,7 @@ message Hop {
     bool tlv_payload = 9;
 
     /**
-    An optional TLV record that signals the use of an MPP payment. If present,
+    An optional TLV record tha singals the use of an MPP payment. If present,
     the receiver will enforce that that the same mpp_record is included in the
     final hop payload of all non-zero payments in the HTLC set. If empty, a
     regular single-shot payment is or was attempted.
diff --git a/lnrpc/rpc.swagger.json b/lnrpc/rpc.swagger.json
index 90859472d..c588125da 100644
--- a/lnrpc/rpc.swagger.json
+++ b/lnrpc/rpc.swagger.json
@@ -3125,7 +3125,7 @@
         },
         "mpp_record": {
           "$ref": "#/definitions/lnrpcMPPRecord",
-          "description": "*\nAn optional TLV record that signals the use of an MPP payment. If present,\nthe receiver will enforce that that the same mpp_record is included in the\nfinal hop payload of all non-zero payments in the HTLC set. If empty, a\nregular single-shot payment is or was attempted."
+          "description": "*\nAn optional TLV record tha singals the use of an MPP payment. If present,\nthe receiver will enforce that that the same mpp_record is included in the\nfinal hop payload of all non-zero payments in the HTLC set. If empty, a\nregular single-shot payment is or was attempted."
         },
         "custom_records": {
           "type": "object",
diff --git a/routing/payment_session.go b/routing/payment_session.go
index f5a49eff0..c5a20f7a1 100644
--- a/routing/payment_session.go
+++ b/routing/payment_session.go
@@ -1,10 +1,6 @@
 package routing
 
 import (
-	"fmt"
-
-	"github.com/btcsuite/btclog"
-	"github.com/lightningnetwork/lnd/build"
 	"github.com/lightningnetwork/lnd/channeldb"
 	"github.com/lightningnetwork/lnd/lnwire"
 	"github.com/lightningnetwork/lnd/routing/route"
@@ -128,36 +124,6 @@ type paymentSession struct {
 	// specified in the payment is one, under no circumstances splitting
 	// will happen and this value remains unused.
 	minShardAmt lnwire.MilliSatoshi
-
-	// log is a payment session-specific logger.
-	log btclog.Logger
-}
-
-// newPaymentSession instantiates a new payment session.
-func newPaymentSession(p *LightningPayment,
-	getBandwidthHints func() (map[uint64]lnwire.MilliSatoshi, error),
-	getRoutingGraph func() (routingGraph, func(), error),
-	missionControl MissionController, pathFindingConfig PathFindingConfig) (
-	*paymentSession, error) {
-
-	edges, err := RouteHintsToEdges(p.RouteHints, p.Target)
-	if err != nil {
-		return nil, err
-	}
-
-	logPrefix := fmt.Sprintf("PaymentSession(%x):", p.PaymentHash)
-
-	return &paymentSession{
-		additionalEdges:   edges,
-		getBandwidthHints: getBandwidthHints,
-		payment:           p,
-		pathFinder:        findPath,
-		getRoutingGraph:   getRoutingGraph,
-		pathFindingConfig: pathFindingConfig,
-		missionControl:    missionControl,
-		minShardAmt:       DefaultShardMinAmt,
-		log:               build.NewPrefixLog(logPrefix, log),
-	}, nil
 }
 
 // RequestRoute returns a route which is likely to be capable for successfully
@@ -216,7 +182,8 @@ func (p *paymentSession) RequestRoute(maxAmt, feeLimit lnwire.MilliSatoshi,
 			return nil, err
 		}
 
-		p.log.Debugf("pathfinding for amt=%v", maxAmt)
+		log.Debugf("PaymentSession for %x: trying pathfinding with %v",
+			p.payment.PaymentHash, maxAmt)
 
 		// Get a routing graph.
 		routingGraph, cleanup, err := p.getRoutingGraph()
@@ -243,22 +210,9 @@ func (p *paymentSession) RequestRoute(maxAmt, feeLimit lnwire.MilliSatoshi,
 
 		switch {
 		case err == errNoPathFound:
-			// Don't split if this is a legacy payment without mpp
-			// record.
-			if p.payment.PaymentAddr == nil {
-				p.log.Debugf("not splitting because payment " +
-					"address is unspecified")
-
-				return nil, errNoPathFound
-			}
-
 			// No splitting if this is the last shard.
 			isLastShard := activeShards+1 >= p.payment.MaxShards
 			if isLastShard {
-				p.log.Debugf("not splitting because shard "+
-					"limit %v has been reached",
-					p.payment.MaxShards)
-
 				return nil, errNoPathFound
 			}
 
@@ -268,10 +222,6 @@ func (p *paymentSession) RequestRoute(maxAmt, feeLimit lnwire.MilliSatoshi,
 
 			// Put a lower bound on the minimum shard size.
 			if maxAmt < p.minShardAmt {
-				p.log.Debugf("not splitting because minimum "+
-					"shard amount %v has been reached",
-					p.minShardAmt)
-
 				return nil, errNoPathFound
 			}
 
diff --git a/routing/payment_session_source.go b/routing/payment_session_source.go
index 8122ff711..a6016ab85 100644
--- a/routing/payment_session_source.go
+++ b/routing/payment_session_source.go
@@ -62,6 +62,11 @@ func (m *SessionSource) getRoutingGraph() (routingGraph, func(), error) {
 func (m *SessionSource) NewPaymentSession(p *LightningPayment) (
 	PaymentSession, error) {
 
+	edges, err := RouteHintsToEdges(p.RouteHints, p.Target)
+	if err != nil {
+		return nil, err
+	}
+
 	sourceNode, err := m.Graph.SourceNode()
 	if err != nil {
 		return nil, err
@@ -73,15 +78,16 @@ func (m *SessionSource) NewPaymentSession(p *LightningPayment) (
 		return generateBandwidthHints(sourceNode, m.QueryBandwidth)
 	}
 
-	session, err := newPaymentSession(
-		p, getBandwidthHints, m.getRoutingGraph,
-		m.MissionControl, m.PathFindingConfig,
-	)
-	if err != nil {
-		return nil, err
-	}
-
-	return session, nil
+	return &paymentSession{
+		additionalEdges:   edges,
+		getBandwidthHints: getBandwidthHints,
+		payment:           p,
+		pathFinder:        findPath,
+		getRoutingGraph:   m.getRoutingGraph,
+		pathFindingConfig: m.PathFindingConfig,
+		missionControl:    m.MissionControl,
+		minShardAmt:       DefaultShardMinAmt,
+	}, nil
 }
 
 // NewPaymentSessionEmpty creates a new paymentSession instance that is empty,


Test patch:
diff --git a/routing/integrated_routing_context_test.go b/routing/integrated_routing_context_test.go
index cc71560d8..457ed4f46 100644
--- a/routing/integrated_routing_context_test.go
+++ b/routing/integrated_routing_context_test.go
@@ -140,20 +140,18 @@ func (c *integratedRoutingContext) testPayment(maxShards uint32) ([]htlcAttempt,
 		MaxShards:      maxShards,
 	}
 
-	session, err := newPaymentSession(
-		&payment, getBandwidthHints,
-		func() (routingGraph, func(), error) {
+	session := &paymentSession{
+		getBandwidthHints: getBandwidthHints,
+		payment:           &payment,
+		pathFinder:        findPath,
+		getRoutingGraph: func() (routingGraph, func(), error) {
 			return c.graph, func() {}, nil
 		},
-		mc, c.pathFindingCfg,
-	)
-	if err != nil {
-		c.t.Fatal(err)
+		pathFindingConfig: c.pathFindingCfg,
+		missionControl:    mc,
+		minShardAmt:       lnwire.NewMSatFromSatoshis(5000),
 	}
 
-	// Override default minimum shard amount.
-	session.minShardAmt = lnwire.NewMSatFromSatoshis(5000)
-
 	// Now the payment control loop starts. It will keep trying routes until
 	// the payment succeeds.
 	var (
diff --git a/routing/payment_session_test.go b/routing/payment_session_test.go
index ba55fcea6..60d960b87 100644
--- a/routing/payment_session_test.go
+++ b/routing/payment_session_test.go
@@ -13,36 +13,9 @@ func TestRequestRoute(t *testing.T) {
 		height = 10
 	)
 
-	cltvLimit := uint32(30)
-	finalCltvDelta := uint16(8)
-
-	payment := &LightningPayment{
-		CltvLimit:      cltvLimit,
-		FinalCLTVDelta: finalCltvDelta,
-		Amount:         1000,
-		FeeLimit:       1000,
-	}
-
-	session, err := newPaymentSession(
-		payment,
-		func() (map[uint64]lnwire.MilliSatoshi,
-			error) {
-
-			return nil, nil
-		},
-		func() (routingGraph, func(), error) {
-			return &sessionGraph{}, func() {}, nil
-		},
-		&MissionControl{cfg: &MissionControlConfig{}},
-		PathFindingConfig{},
-	)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	// Override pathfinder with a mock.
-	session.pathFinder = func(
-		g *graphParams, r *RestrictParams, cfg *PathFindingConfig,
+	findPath := func(
+		g *graphParams,
+		r *RestrictParams, cfg *PathFindingConfig,
 		source, target route.Vertex, amt lnwire.MilliSatoshi,
 		finalHtlcExpiry int32) ([]*channeldb.ChannelEdgePolicy, error) {
 
@@ -65,6 +38,32 @@ func TestRequestRoute(t *testing.T) {
 		return path, nil
 	}
 
+	cltvLimit := uint32(30)
+	finalCltvDelta := uint16(8)
+
+	payment := &LightningPayment{
+		CltvLimit:      cltvLimit,
+		FinalCLTVDelta: finalCltvDelta,
+		Amount:         1000,
+		FeeLimit:       1000,
+	}
+
+	session := &paymentSession{
+		getBandwidthHints: func() (map[uint64]lnwire.MilliSatoshi,
+			error) {
+
+			return nil, nil
+		},
+		payment:    payment,
+		pathFinder: findPath,
+		missionControl: &MissionControl{
+			cfg: &MissionControlConfig{},
+		},
+		getRoutingGraph: func() (routingGraph, func(), error) {
+			return &sessionGraph{}, func() {}, nil
+		},
+	}
+
 	route, err := session.RequestRoute(
 		payment.Amount, payment.FeeLimit, 0, height,
 	)