@@ -24,6 +24,7 @@ import (
2424 "github.com/btcsuite/btcd/chaincfg/chainhash"
2525 "github.com/btcsuite/btcd/wire"
2626 "github.com/lightninglabs/faraday/frdrpc"
27+ "github.com/lightninglabs/lightning-terminal/litrpc"
2728 "github.com/lightninglabs/loop/looprpc"
2829 "github.com/lightninglabs/pool/poolrpc"
2930 "github.com/lightningnetwork/lnd/lnrpc"
@@ -231,9 +232,13 @@ type HarnessNode struct {
231232 // methods SignMessage and VerifyMessage.
232233 SignerClient signrpc.SignerClient
233234
234- // conn is the underlying connection to the grpc endpoint of the node.
235+ // conn is the underlying connection to the lnd grpc endpoint of the
236+ // node.
235237 conn * grpc.ClientConn
236238
239+ // litConn is the underlying connection to Lit's grpc endpoint.
240+ litConn * grpc.ClientConn
241+
237242 // RouterClient, WalletKitClient, WatchtowerClient cannot be embedded,
238243 // because a name collision would occur with LightningClient.
239244 RouterClient routerrpc.RouterClient
@@ -578,7 +583,22 @@ func (hn *HarnessNode) start(litdBinary string, litdError chan<- error,
578583 return nil
579584 }
580585
581- return hn .initLightningClient (conn )
586+ err = hn .initLightningClient (conn )
587+ if err != nil {
588+ return fmt .Errorf ("could not init Lightning Client: %w" , err )
589+ }
590+
591+ // Also connect to Lit's RPC port for any Litd specific calls.
592+ litConn , err := connectLitRPC (
593+ context .Background (), hn .Cfg .LitAddr (), hn .Cfg .LitTLSCertPath ,
594+ hn .Cfg .LitMacPath ,
595+ )
596+ if err != nil {
597+ return fmt .Errorf ("could not connect to Lit RPC: %w" , err )
598+ }
599+ hn .litConn = litConn
600+
601+ return nil
582602}
583603
584604// WaitUntilStarted waits until the wallet state flips from "WAITING_TO_START".
@@ -1044,6 +1064,14 @@ func (hn *HarnessNode) SetExtraArgs(extraArgs []string) {
10441064
10451065// cleanup cleans up all the temporary files created by the node's process.
10461066func (hn * HarnessNode ) cleanup () error {
1067+ if hn .Cfg .RemoteMode {
1068+ err := hn .RemoteLnd .Shutdown ()
1069+ if err != nil {
1070+ return fmt .Errorf ("unable to shutdown remote lnd " +
1071+ "dir: %v" , err )
1072+ }
1073+ }
1074+
10471075 if hn .backupDbDir != "" {
10481076 err := os .RemoveAll (hn .backupDbDir )
10491077 if err != nil {
@@ -1054,7 +1082,7 @@ func (hn *HarnessNode) cleanup() error {
10541082 return os .RemoveAll (hn .Cfg .BaseDir )
10551083}
10561084
1057- // Stop attempts to stop the active lnd process.
1085+ // Stop attempts to stop the active litd process.
10581086func (hn * HarnessNode ) stop () error {
10591087 // Do nothing if the process is not running.
10601088 if hn .processExit == nil {
@@ -1063,9 +1091,9 @@ func (hn *HarnessNode) stop() error {
10631091
10641092 // If start() failed before creating a client, we will just wait for the
10651093 // child process to die.
1066- if hn .LightningClient != nil {
1067- // Don't watch for error because sometimes the RPC connection gets
1068- // closed before a response is returned.
1094+ if ! hn . Cfg . RemoteMode && hn .LightningClient != nil {
1095+ // Don't watch for error because sometimes the RPC connection
1096+ // gets closed before a response is returned.
10691097 req := lnrpc.StopRequest {}
10701098 ctx := context .Background ()
10711099
@@ -1086,9 +1114,22 @@ func (hn *HarnessNode) stop() error {
10861114 if err != nil {
10871115 return err
10881116 }
1117+ } else if hn .Cfg .RemoteMode {
1118+ // If lit is running in remote mode, then calling LNDs
1119+ // StopDaemon method will not shut down Lit, and so we need to
1120+ // explicitly request lit to shut down.
1121+ ctx , cancel := context .WithTimeout (
1122+ context .Background (), lntest .DefaultTimeout ,
1123+ )
1124+ litConn := litrpc .NewProxyClient (hn .litConn )
1125+ _ , err := litConn .StopDaemon (ctx , & litrpc.StopDaemonRequest {})
1126+ cancel ()
1127+ if err != nil {
1128+ return err
1129+ }
10891130 }
10901131
1091- // Wait for lnd process and other goroutines to exit.
1132+ // Wait for litd process and other goroutines to exit.
10921133 select {
10931134 case <- hn .processExit :
10941135 case <- time .After (lntest .DefaultTimeout * 2 ):
@@ -1116,10 +1157,6 @@ func (hn *HarnessNode) stop() error {
11161157 }
11171158 }
11181159
1119- if hn .Cfg .RemoteMode {
1120- return hn .RemoteLnd .Shutdown ()
1121- }
1122-
11231160 return nil
11241161}
11251162
@@ -1782,3 +1819,40 @@ func (hn *HarnessNode) getChannelPolicies(include bool) policyUpdateMap {
17821819
17831820 return policyUpdates
17841821}
1822+
1823+ // connectLitRPC can be used to connect to the lit rpc server.
1824+ func connectLitRPC (ctx context.Context , hostPort , tlsCertPath ,
1825+ macPath string ) (* grpc.ClientConn , error ) {
1826+
1827+ tlsCreds , err := credentials .NewClientTLSFromFile (tlsCertPath , "" )
1828+ if err != nil {
1829+ return nil , err
1830+ }
1831+
1832+ opts := []grpc.DialOption {
1833+ grpc .WithBlock (),
1834+ grpc .WithTransportCredentials (tlsCreds ),
1835+ }
1836+
1837+ if macPath != "" {
1838+ macBytes , err := ioutil .ReadFile (macPath )
1839+ if err != nil {
1840+ return nil , err
1841+ }
1842+
1843+ mac := & macaroon.Macaroon {}
1844+ if err = mac .UnmarshalBinary (macBytes ); err != nil {
1845+ return nil , fmt .Errorf ("error unmarshalling macaroon " +
1846+ "file: %v" , err )
1847+ }
1848+
1849+ macCred , err := macaroons .NewMacaroonCredential (mac )
1850+ if err != nil {
1851+ return nil , fmt .Errorf ("error cloning mac: %v" , err )
1852+ }
1853+
1854+ opts = append (opts , grpc .WithPerRPCCredentials (macCred ))
1855+ }
1856+
1857+ return grpc .DialContext (ctx , hostPort , opts ... )
1858+ }
0 commit comments