@@ -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)
@@ -495,6 +498,85 @@ func (s *swapClientServer) GetLoopInQuote(ctx context.Context,
495498 }, nil
496499}
497500
501+ // unmarshallRouteHints unmarshalls a list of route hints.
502+ func unmarshallRouteHints (rpcRouteHints []* looprpc.RouteHint ) (
503+ [][]zpay32.HopHint , error ) {
504+
505+ routeHints := make ([][]zpay32.HopHint , 0 , len (rpcRouteHints ))
506+ for _ , rpcRouteHint := range rpcRouteHints {
507+ routeHint := make (
508+ []zpay32.HopHint , 0 , len (rpcRouteHint .HopHints ),
509+ )
510+ for _ , rpcHint := range rpcRouteHint .HopHints {
511+ hint , err := unmarshallHopHint (rpcHint )
512+ if err != nil {
513+ return nil , err
514+ }
515+
516+ routeHint = append (routeHint , hint )
517+ }
518+ routeHints = append (routeHints , routeHint )
519+ }
520+
521+ return routeHints , nil
522+ }
523+
524+ // unmarshallHopHint unmarshalls a single hop hint.
525+ func unmarshallHopHint (rpcHint * looprpc.HopHint ) (zpay32.HopHint , error ) {
526+ pubBytes , err := hex .DecodeString (rpcHint .NodeId )
527+ if err != nil {
528+ return zpay32.HopHint {}, err
529+ }
530+
531+ pubkey , err := btcec .ParsePubKey (pubBytes , btcec .S256 ())
532+ if err != nil {
533+ return zpay32.HopHint {}, err
534+ }
535+
536+ return zpay32.HopHint {
537+ NodeID : pubkey ,
538+ ChannelID : rpcHint .ChanId ,
539+ FeeBaseMSat : rpcHint .FeeBaseMsat ,
540+ FeeProportionalMillionths : rpcHint .FeeProportionalMillionths ,
541+ CLTVExpiryDelta : uint16 (rpcHint .CltvExpiryDelta ),
542+ }, nil
543+ }
544+
545+ // Probe requests the server to probe the client's node to test inbound
546+ // liquidity.
547+ func (s * swapClientServer ) Probe (ctx context.Context ,
548+ req * looprpc.ProbeRequest ) (* looprpc.ProbeResponse , error ) {
549+
550+ log .Infof ("Probe request received" )
551+
552+ var lastHop * route.Vertex
553+ if req .LastHop != nil {
554+ lastHopVertex , err := route .NewVertexFromBytes (req .LastHop )
555+ if err != nil {
556+ return nil , err
557+ }
558+
559+ lastHop = & lastHopVertex
560+ }
561+
562+ routeHints , err := unmarshallRouteHints (req .RouteHints )
563+ if err != nil {
564+ return nil , err
565+ }
566+
567+ err = s .impl .Probe (ctx , & loop.ProbeRequest {
568+ Amount : btcutil .Amount (req .Amt ),
569+ LastHop : lastHop ,
570+ RouteHints : routeHints ,
571+ })
572+
573+ if err != nil {
574+ return nil , err
575+ }
576+
577+ return & looprpc.ProbeResponse {}, nil
578+ }
579+
498580func (s * swapClientServer ) LoopIn (ctx context.Context ,
499581 in * looprpc.LoopInRequest ) (
500582 * looprpc.SwapResponse , error ) {
0 commit comments