@@ -2,12 +2,14 @@ package loopd
22
33import (
44 "context"
5+ "encoding/hex"
56 "errors"
67 "fmt"
78 "sort"
89 "sync"
910 "time"
1011
12+ "github.com/btcsuite/btcd/btcec"
1113 "github.com/btcsuite/btcd/chaincfg"
1214 "github.com/btcsuite/btcutil"
1315 "github.com/lightninglabs/lndclient"
@@ -22,6 +24,7 @@ import (
2224 "github.com/lightningnetwork/lnd/lnwire"
2325 "github.com/lightningnetwork/lnd/queue"
2426 "github.com/lightningnetwork/lnd/routing/route"
27+ "github.com/lightningnetwork/lnd/zpay32"
2528 "google.golang.org/grpc/codes"
2629 "google.golang.org/grpc/status"
2730)
@@ -480,10 +483,29 @@ func (s *swapClientServer) GetLoopInQuote(ctx context.Context,
480483 return nil , err
481484 }
482485
486+ var lastHop * route.Vertex
487+ if req .LoopInLastHop != nil {
488+ lastHopVertex , err := route .NewVertexFromBytes (
489+ req .LoopInLastHop ,
490+ )
491+ if err != nil {
492+ return nil , err
493+ }
494+
495+ lastHop = & lastHopVertex
496+ }
497+
498+ routeHints , err := unmarshallRouteHints (req .LoopInRouteHints )
499+ if err != nil {
500+ return nil , err
501+ }
502+
483503 quote , err := s .impl .LoopInQuote (ctx , & loop.LoopInQuoteRequest {
484504 Amount : btcutil .Amount (req .Amt ),
485505 HtlcConfTarget : htlcConfTarget ,
486506 ExternalHtlc : req .ExternalHtlc ,
507+ LastHop : lastHop ,
508+ RouteHints : routeHints ,
487509 })
488510 if err != nil {
489511 return nil , err
@@ -495,6 +517,84 @@ func (s *swapClientServer) GetLoopInQuote(ctx context.Context,
495517 }, nil
496518}
497519
520+ // unmarshallRouteHints unmarshalls a list of route hints.
521+ func unmarshallRouteHints (rpcRouteHints []* looprpc.RouteHint ) (
522+ [][]zpay32.HopHint , error ) {
523+
524+ routeHints := make ([][]zpay32.HopHint , 0 , len (rpcRouteHints ))
525+ for _ , rpcRouteHint := range rpcRouteHints {
526+ routeHint := make (
527+ []zpay32.HopHint , 0 , len (rpcRouteHint .HopHints ),
528+ )
529+ for _ , rpcHint := range rpcRouteHint .HopHints {
530+ hint , err := unmarshallHopHint (rpcHint )
531+ if err != nil {
532+ return nil , err
533+ }
534+
535+ routeHint = append (routeHint , hint )
536+ }
537+ routeHints = append (routeHints , routeHint )
538+ }
539+
540+ return routeHints , nil
541+ }
542+
543+ // unmarshallHopHint unmarshalls a single hop hint.
544+ func unmarshallHopHint (rpcHint * looprpc.HopHint ) (zpay32.HopHint , error ) {
545+ pubBytes , err := hex .DecodeString (rpcHint .NodeId )
546+ if err != nil {
547+ return zpay32.HopHint {}, err
548+ }
549+
550+ pubkey , err := btcec .ParsePubKey (pubBytes , btcec .S256 ())
551+ if err != nil {
552+ return zpay32.HopHint {}, err
553+ }
554+
555+ return zpay32.HopHint {
556+ NodeID : pubkey ,
557+ ChannelID : rpcHint .ChanId ,
558+ FeeBaseMSat : rpcHint .FeeBaseMsat ,
559+ FeeProportionalMillionths : rpcHint .FeeProportionalMillionths ,
560+ CLTVExpiryDelta : uint16 (rpcHint .CltvExpiryDelta ),
561+ }, nil
562+ }
563+
564+ // Probe requests the server to probe the client's node to test inbound
565+ // liquidity.
566+ func (s * swapClientServer ) Probe (ctx context.Context ,
567+ req * looprpc.ProbeRequest ) (* looprpc.ProbeResponse , error ) {
568+
569+ log .Infof ("Probe request received" )
570+
571+ var lastHop * route.Vertex
572+ if req .LastHop != nil {
573+ lastHopVertex , err := route .NewVertexFromBytes (req .LastHop )
574+ if err != nil {
575+ return nil , err
576+ }
577+
578+ lastHop = & lastHopVertex
579+ }
580+
581+ routeHints , err := unmarshallRouteHints (req .RouteHints )
582+ if err != nil {
583+ return nil , err
584+ }
585+
586+ err = s .impl .Probe (ctx , & loop.ProbeRequest {
587+ Amount : btcutil .Amount (req .Amt ),
588+ LastHop : lastHop ,
589+ RouteHints : routeHints ,
590+ })
591+ if err != nil {
592+ return nil , err
593+ }
594+
595+ return & looprpc.ProbeResponse {}, nil
596+ }
597+
498598func (s * swapClientServer ) LoopIn (ctx context.Context ,
499599 in * looprpc.LoopInRequest ) (
500600 * looprpc.SwapResponse , error ) {
0 commit comments