2019-03-06 20:13:50 +00:00
|
|
|
package lndclient
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2020-04-22 13:48:11 +00:00
|
|
|
"errors"
|
2019-03-06 20:13:50 +00:00
|
|
|
"fmt"
|
2020-01-03 13:01:31 +00:00
|
|
|
"net"
|
2019-03-06 20:13:50 +00:00
|
|
|
"path/filepath"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/btcsuite/btcd/chaincfg"
|
|
|
|
"github.com/btcsuite/btcutil"
|
2019-03-07 02:22:46 +00:00
|
|
|
"github.com/lightninglabs/loop/swap"
|
2019-03-06 20:13:50 +00:00
|
|
|
"github.com/lightningnetwork/lnd/lncfg"
|
2020-04-22 13:48:11 +00:00
|
|
|
"github.com/lightningnetwork/lnd/lnrpc/verrpc"
|
2019-03-06 20:13:50 +00:00
|
|
|
"google.golang.org/grpc"
|
2020-04-22 13:48:11 +00:00
|
|
|
"google.golang.org/grpc/codes"
|
2019-03-06 20:13:50 +00:00
|
|
|
"google.golang.org/grpc/credentials"
|
2020-04-22 13:48:11 +00:00
|
|
|
"google.golang.org/grpc/status"
|
2019-03-06 20:13:50 +00:00
|
|
|
)
|
|
|
|
|
2020-04-22 13:48:11 +00:00
|
|
|
var (
|
|
|
|
rpcTimeout = 30 * time.Second
|
|
|
|
|
|
|
|
// minimalCompatibleVersion is the minimum version and build tags
|
|
|
|
// required in lnd to get all functionality implemented in lndclient.
|
|
|
|
// Users can provide their own, specific version if needed. If only a
|
|
|
|
// subset of the lndclient functionality is needed, the required build
|
|
|
|
// tags can be adjusted accordingly. This default will be used as a fall
|
|
|
|
// back version if none is specified in the configuration.
|
|
|
|
minimalCompatibleVersion = &verrpc.Version{
|
|
|
|
AppMajor: 0,
|
|
|
|
AppMinor: 10,
|
|
|
|
AppPatch: 0,
|
|
|
|
BuildTags: []string{
|
|
|
|
"signrpc", "walletrpc", "chainrpc", "invoicesrpc",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
// ErrVersionCheckNotImplemented is the error that is returned if the
|
|
|
|
// version RPC is not implemented in lnd. This means the version of lnd
|
|
|
|
// is lower than v0.10.0-beta.
|
|
|
|
ErrVersionCheckNotImplemented = errors.New("version check not " +
|
|
|
|
"implemented, need minimum lnd version of v0.10.0-beta")
|
|
|
|
|
|
|
|
// ErrVersionIncompatible is the error that is returned if the connected
|
|
|
|
// lnd instance is not supported.
|
|
|
|
ErrVersionIncompatible = errors.New("version incompatible")
|
|
|
|
|
|
|
|
// ErrBuildTagsMissing is the error that is returned if the
|
|
|
|
// connected lnd instance does not have all built tags activated that
|
|
|
|
// are required.
|
|
|
|
ErrBuildTagsMissing = errors.New("build tags missing")
|
|
|
|
)
|
2019-03-06 20:13:50 +00:00
|
|
|
|
2020-04-22 12:29:31 +00:00
|
|
|
// LndServicesConfig holds all configuration settings that are needed to connect
|
|
|
|
// to an lnd node.
|
|
|
|
type LndServicesConfig struct {
|
|
|
|
// LndAddress is the network address (host:port) of the lnd node to
|
|
|
|
// connect to.
|
|
|
|
LndAddress string
|
|
|
|
|
|
|
|
// Network is the bitcoin network we expect the lnd node to operate on.
|
|
|
|
Network string
|
|
|
|
|
|
|
|
// MacaroonDir is the directory where all lnd macaroons can be found.
|
|
|
|
MacaroonDir string
|
|
|
|
|
|
|
|
// TLSPath is the path to lnd's TLS certificate file.
|
|
|
|
TLSPath string
|
|
|
|
|
2020-04-22 13:48:11 +00:00
|
|
|
// CheckVersion is the minimum version the connected lnd node needs to
|
|
|
|
// be in order to be compatible. The node will be checked against this
|
|
|
|
// when connecting. If no version is supplied, the default minimum
|
|
|
|
// version will be used.
|
|
|
|
CheckVersion *verrpc.Version
|
|
|
|
|
2020-04-22 12:29:31 +00:00
|
|
|
// Dialer is an optional dial function that can be passed in if the
|
|
|
|
// default lncfg.ClientAddressDialer should not be used.
|
|
|
|
Dialer DialerFunc
|
|
|
|
}
|
|
|
|
|
|
|
|
// DialerFunc is a function that is used as grpc.WithContextDialer().
|
|
|
|
type DialerFunc func(context.Context, string) (net.Conn, error)
|
|
|
|
|
2019-03-06 20:13:50 +00:00
|
|
|
// LndServices constitutes a set of required services.
|
|
|
|
type LndServices struct {
|
|
|
|
Client LightningClient
|
|
|
|
WalletKit WalletKitClient
|
|
|
|
ChainNotifier ChainNotifierClient
|
|
|
|
Signer SignerClient
|
|
|
|
Invoices InvoicesClient
|
2019-03-25 09:31:03 +00:00
|
|
|
Router RouterClient
|
2020-04-24 07:20:42 +00:00
|
|
|
Versioner VersionerClient
|
2019-03-06 20:13:50 +00:00
|
|
|
|
|
|
|
ChainParams *chaincfg.Params
|
2020-04-24 07:27:25 +00:00
|
|
|
NodeAlias string
|
|
|
|
NodePubkey [33]byte
|
2020-04-22 13:48:11 +00:00
|
|
|
Version *verrpc.Version
|
2019-04-17 02:15:10 +00:00
|
|
|
|
|
|
|
macaroons *macaroonPouch
|
2019-03-06 20:13:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// GrpcLndServices constitutes a set of required RPC services.
|
|
|
|
type GrpcLndServices struct {
|
|
|
|
LndServices
|
|
|
|
|
|
|
|
cleanup func()
|
|
|
|
}
|
|
|
|
|
2020-01-03 13:01:31 +00:00
|
|
|
// NewLndServices creates creates a connection to the given lnd instance and
|
|
|
|
// creates a set of required RPC services.
|
2020-04-22 12:29:31 +00:00
|
|
|
func NewLndServices(cfg *LndServicesConfig) (*GrpcLndServices, error) {
|
2020-01-03 13:01:31 +00:00
|
|
|
// We need to use a custom dialer so we can also connect to unix
|
|
|
|
// sockets and not just TCP addresses.
|
2020-04-22 12:29:31 +00:00
|
|
|
if cfg.Dialer == nil {
|
|
|
|
cfg.Dialer = lncfg.ClientAddressDialer(defaultRPCPort)
|
|
|
|
}
|
2019-04-17 02:15:10 +00:00
|
|
|
|
2020-04-22 13:48:11 +00:00
|
|
|
// Fall back to minimal compatible version if none if specified.
|
|
|
|
if cfg.CheckVersion == nil {
|
|
|
|
cfg.CheckVersion = minimalCompatibleVersion
|
|
|
|
}
|
|
|
|
|
2019-04-17 02:18:28 +00:00
|
|
|
// Based on the network, if the macaroon directory isn't set, then
|
|
|
|
// we'll use the expected default locations.
|
2020-04-22 12:29:31 +00:00
|
|
|
macaroonDir := cfg.MacaroonDir
|
2019-04-17 02:15:10 +00:00
|
|
|
if macaroonDir == "" {
|
2020-04-22 12:29:31 +00:00
|
|
|
switch cfg.Network {
|
2019-04-17 02:18:28 +00:00
|
|
|
case "testnet":
|
|
|
|
macaroonDir = filepath.Join(
|
|
|
|
defaultLndDir, defaultDataDir,
|
|
|
|
defaultChainSubDir, "bitcoin", "testnet",
|
|
|
|
)
|
|
|
|
|
|
|
|
case "mainnet":
|
|
|
|
macaroonDir = filepath.Join(
|
|
|
|
defaultLndDir, defaultDataDir,
|
|
|
|
defaultChainSubDir, "bitcoin", "mainnet",
|
|
|
|
)
|
|
|
|
|
|
|
|
case "simnet":
|
|
|
|
macaroonDir = filepath.Join(
|
|
|
|
defaultLndDir, defaultDataDir,
|
|
|
|
defaultChainSubDir, "bitcoin", "simnet",
|
|
|
|
)
|
|
|
|
|
|
|
|
case "regtest":
|
|
|
|
macaroonDir = filepath.Join(
|
|
|
|
defaultLndDir, defaultDataDir,
|
|
|
|
defaultChainSubDir, "bitcoin", "regtest",
|
|
|
|
)
|
|
|
|
|
|
|
|
default:
|
|
|
|
return nil, fmt.Errorf("unsupported network: %v",
|
2020-04-22 12:29:31 +00:00
|
|
|
cfg.Network)
|
2019-04-17 02:18:28 +00:00
|
|
|
}
|
2019-04-17 02:15:10 +00:00
|
|
|
}
|
|
|
|
|
2019-03-06 20:13:50 +00:00
|
|
|
// Setup connection with lnd
|
2020-04-22 12:29:31 +00:00
|
|
|
log.Infof("Creating lnd connection to %v", cfg.LndAddress)
|
|
|
|
conn, err := getClientConn(cfg)
|
2019-03-06 20:13:50 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-10-28 16:06:07 +00:00
|
|
|
log.Infof("Connected to lnd")
|
2019-03-06 20:13:50 +00:00
|
|
|
|
2020-04-22 12:29:31 +00:00
|
|
|
chainParams, err := swap.ChainParamsFromNetwork(cfg.Network)
|
2019-03-06 20:13:50 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2020-04-22 12:12:17 +00:00
|
|
|
// We are going to check that the connected lnd is on the same network
|
|
|
|
// and is a compatible version with all the required subservers enabled.
|
|
|
|
// For this, we make two calls, both of which only need the readonly
|
|
|
|
// macaroon. We don't use the pouch yet because if not all subservers
|
|
|
|
// are enabled, then not all macaroons might be there and the user would
|
|
|
|
// get a more cryptic error message.
|
|
|
|
readonlyMac, err := newSerializedMacaroon(
|
|
|
|
filepath.Join(macaroonDir, defaultReadonlyFilename),
|
2019-04-17 02:17:19 +00:00
|
|
|
)
|
2019-03-06 20:13:50 +00:00
|
|
|
if err != nil {
|
2020-04-22 12:12:17 +00:00
|
|
|
return nil, err
|
2019-03-06 20:13:50 +00:00
|
|
|
}
|
2020-04-22 13:48:11 +00:00
|
|
|
nodeAlias, nodeKey, version, err := checkLndCompatibility(
|
|
|
|
conn, chainParams, readonlyMac, cfg.Network, cfg.CheckVersion,
|
2020-04-24 07:27:25 +00:00
|
|
|
)
|
2020-04-22 12:12:17 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now that we've ensured our macaroon directory is set properly, we
|
|
|
|
// can retrieve our full macaroon pouch from the directory.
|
|
|
|
macaroons, err := newMacaroonPouch(macaroonDir)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("unable to obtain macaroons: %v", err)
|
2019-03-06 20:13:50 +00:00
|
|
|
}
|
|
|
|
|
2020-04-22 12:12:17 +00:00
|
|
|
// With the macaroons loaded and the version checked, we can now create
|
|
|
|
// the real lightning client which uses the admin macaroon.
|
|
|
|
lightningClient := newLightningClient(
|
|
|
|
conn, chainParams, macaroons.adminMac,
|
|
|
|
)
|
|
|
|
|
2019-04-17 02:17:19 +00:00
|
|
|
// With the network check passed, we'll now initialize the rest of the
|
2019-04-17 02:18:28 +00:00
|
|
|
// sub-server connections, giving each of them their specific macaroon.
|
2019-04-17 02:17:19 +00:00
|
|
|
notifierClient := newChainNotifierClient(conn, macaroons.chainMac)
|
|
|
|
signerClient := newSignerClient(conn, macaroons.signerMac)
|
|
|
|
walletKitClient := newWalletKitClient(conn, macaroons.walletKitMac)
|
|
|
|
invoicesClient := newInvoicesClient(conn, macaroons.invoiceMac)
|
2019-03-25 09:31:03 +00:00
|
|
|
routerClient := newRouterClient(conn, macaroons.routerMac)
|
2020-04-24 07:20:42 +00:00
|
|
|
versionerClient := newVersionerClient(conn, macaroons.readonlyMac)
|
2019-03-06 20:13:50 +00:00
|
|
|
|
|
|
|
cleanup := func() {
|
2019-10-28 16:06:07 +00:00
|
|
|
log.Debugf("Closing lnd connection")
|
2020-04-22 12:12:17 +00:00
|
|
|
err := conn.Close()
|
|
|
|
if err != nil {
|
|
|
|
log.Errorf("Error closing client connection: %v", err)
|
|
|
|
}
|
2019-03-06 20:13:50 +00:00
|
|
|
|
2019-10-28 16:06:07 +00:00
|
|
|
log.Debugf("Wait for client to finish")
|
2019-03-06 20:13:50 +00:00
|
|
|
lightningClient.WaitForFinished()
|
|
|
|
|
2019-10-28 16:06:07 +00:00
|
|
|
log.Debugf("Wait for chain notifier to finish")
|
2019-03-06 20:13:50 +00:00
|
|
|
notifierClient.WaitForFinished()
|
|
|
|
|
2019-10-28 16:06:07 +00:00
|
|
|
log.Debugf("Wait for invoices to finish")
|
2019-03-06 20:13:50 +00:00
|
|
|
invoicesClient.WaitForFinished()
|
|
|
|
|
2019-10-28 16:06:07 +00:00
|
|
|
log.Debugf("Lnd services finished")
|
2019-03-06 20:13:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
services := &GrpcLndServices{
|
|
|
|
LndServices: LndServices{
|
|
|
|
Client: lightningClient,
|
|
|
|
WalletKit: walletKitClient,
|
|
|
|
ChainNotifier: notifierClient,
|
|
|
|
Signer: signerClient,
|
|
|
|
Invoices: invoicesClient,
|
2019-03-25 09:31:03 +00:00
|
|
|
Router: routerClient,
|
2020-04-24 07:20:42 +00:00
|
|
|
Versioner: versionerClient,
|
2019-03-06 20:13:50 +00:00
|
|
|
ChainParams: chainParams,
|
2020-04-24 07:27:25 +00:00
|
|
|
NodeAlias: nodeAlias,
|
|
|
|
NodePubkey: nodeKey,
|
2020-04-22 13:48:11 +00:00
|
|
|
Version: version,
|
2019-04-17 02:15:10 +00:00
|
|
|
macaroons: macaroons,
|
2019-03-06 20:13:50 +00:00
|
|
|
},
|
|
|
|
cleanup: cleanup,
|
|
|
|
}
|
|
|
|
|
2020-04-22 12:29:31 +00:00
|
|
|
log.Infof("Using network %v", cfg.Network)
|
2019-03-06 20:13:50 +00:00
|
|
|
|
|
|
|
return services, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Close closes the lnd connection and waits for all sub server clients to
|
|
|
|
// finish their goroutines.
|
|
|
|
func (s *GrpcLndServices) Close() {
|
|
|
|
s.cleanup()
|
|
|
|
|
2019-10-28 16:06:07 +00:00
|
|
|
log.Debugf("Lnd services finished")
|
2019-03-06 20:13:50 +00:00
|
|
|
}
|
|
|
|
|
2020-04-22 12:12:17 +00:00
|
|
|
// checkLndCompatibility makes sure the connected lnd instance is running on the
|
2020-04-22 13:48:11 +00:00
|
|
|
// correct network, has the version RPC implemented, is the correct minimal
|
|
|
|
// version and supports all required build tags/subservers.
|
2020-04-22 12:12:17 +00:00
|
|
|
func checkLndCompatibility(conn *grpc.ClientConn, chainParams *chaincfg.Params,
|
2020-04-22 13:48:11 +00:00
|
|
|
readonlyMac serializedMacaroon, network string,
|
|
|
|
minVersion *verrpc.Version) (string, [33]byte, *verrpc.Version, error) {
|
2020-04-24 07:27:25 +00:00
|
|
|
|
|
|
|
// onErr is a closure that simplifies returning multiple values in the
|
|
|
|
// error case.
|
2020-04-22 13:48:11 +00:00
|
|
|
onErr := func(err error) (string, [33]byte, *verrpc.Version, error) {
|
2020-04-24 07:27:25 +00:00
|
|
|
closeErr := conn.Close()
|
|
|
|
if closeErr != nil {
|
|
|
|
log.Errorf("Error closing lnd connection: %v", closeErr)
|
|
|
|
}
|
|
|
|
|
2020-04-22 13:48:11 +00:00
|
|
|
// Make static error messages a bit less cryptic by adding the
|
|
|
|
// version or build tag that we expect.
|
|
|
|
newErr := fmt.Errorf("lnd compatibility check failed: %v", err)
|
|
|
|
if err == ErrVersionIncompatible || err == ErrBuildTagsMissing {
|
|
|
|
newErr = fmt.Errorf("error checking connected lnd "+
|
|
|
|
"version. at least version \"%s\" is "+
|
|
|
|
"required", VersionString(minVersion))
|
|
|
|
}
|
|
|
|
|
|
|
|
return "", [33]byte{}, nil, newErr
|
2020-04-24 07:27:25 +00:00
|
|
|
}
|
2020-04-22 12:12:17 +00:00
|
|
|
|
2020-04-22 13:48:11 +00:00
|
|
|
// We use our own clients with a readonly macaroon here, because we know
|
2020-04-22 12:12:17 +00:00
|
|
|
// that's all we need for the checks.
|
|
|
|
lightningClient := newLightningClient(conn, chainParams, readonlyMac)
|
2020-04-22 13:48:11 +00:00
|
|
|
versionerClient := newVersionerClient(conn, readonlyMac)
|
2020-04-22 12:12:17 +00:00
|
|
|
|
|
|
|
// With our readonly macaroon obtained, we'll ensure that the network
|
|
|
|
// for lnd matches our expected network.
|
|
|
|
info, err := lightningClient.GetInfo(context.Background())
|
|
|
|
if err != nil {
|
2020-04-24 07:27:25 +00:00
|
|
|
err := fmt.Errorf("unable to get info for lnd node: %v", err)
|
|
|
|
return onErr(err)
|
2020-04-22 12:12:17 +00:00
|
|
|
}
|
|
|
|
if network != info.Network {
|
2020-04-24 07:27:25 +00:00
|
|
|
err := fmt.Errorf("network mismatch with connected lnd node, "+
|
|
|
|
"wanted '%s', got '%s'", network, info.Network)
|
|
|
|
return onErr(err)
|
2020-04-22 12:12:17 +00:00
|
|
|
}
|
2020-04-24 07:27:25 +00:00
|
|
|
|
2020-04-22 13:48:11 +00:00
|
|
|
// Now let's also check the version of the connected lnd node.
|
|
|
|
version, err := checkVersionCompatibility(versionerClient, minVersion)
|
|
|
|
if err != nil {
|
|
|
|
return onErr(err)
|
|
|
|
}
|
|
|
|
|
2020-04-24 07:27:25 +00:00
|
|
|
// Return the static part of the info we just queried from the node so
|
|
|
|
// it can be cached for later use.
|
2020-04-22 13:48:11 +00:00
|
|
|
return info.Alias, info.IdentityPubkey, version, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// checkVersionCompatibility makes sure the connected lnd node has the correct
|
|
|
|
// version and required build tags enabled.
|
|
|
|
//
|
|
|
|
// NOTE: This check will **never** return a non-nil error for a version of
|
|
|
|
// lnd < 0.10.0 because any version previous to 0.10.0 doesn't have the version
|
|
|
|
// endpoint implemented!
|
|
|
|
func checkVersionCompatibility(client VersionerClient,
|
|
|
|
expected *verrpc.Version) (*verrpc.Version, error) {
|
|
|
|
|
|
|
|
// First, test that the version RPC is even implemented.
|
|
|
|
version, err := client.GetVersion(context.Background())
|
|
|
|
if err != nil {
|
|
|
|
// The version service has only been added in lnd v0.10.0. If
|
|
|
|
// we get an unimplemented error, it means the lnd version is
|
|
|
|
// definitely older than that.
|
|
|
|
s, ok := status.FromError(err)
|
|
|
|
if ok && s.Code() == codes.Unimplemented {
|
|
|
|
return nil, ErrVersionCheckNotImplemented
|
|
|
|
}
|
|
|
|
return nil, fmt.Errorf("GetVersion error: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now check the version and make sure all required build tags are set.
|
|
|
|
err = assertVersionCompatible(version, expected)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
err = assertBuildTagsEnabled(version, expected.BuildTags)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// All check positive, version is fully compatible.
|
|
|
|
return version, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// assertVersionCompatible makes sure the detected lnd version is compatible
|
|
|
|
// with our current version requirements.
|
|
|
|
func assertVersionCompatible(actual *verrpc.Version,
|
|
|
|
expected *verrpc.Version) error {
|
|
|
|
|
|
|
|
// We need to check the versions parts sequentially as they are
|
|
|
|
// hierarchical.
|
|
|
|
if actual.AppMajor != expected.AppMajor {
|
|
|
|
if actual.AppMajor > expected.AppMajor {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return ErrVersionIncompatible
|
|
|
|
}
|
|
|
|
|
|
|
|
if actual.AppMinor != expected.AppMinor {
|
|
|
|
if actual.AppMinor > expected.AppMinor {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return ErrVersionIncompatible
|
|
|
|
}
|
|
|
|
|
|
|
|
if actual.AppPatch != expected.AppPatch {
|
|
|
|
if actual.AppPatch > expected.AppPatch {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return ErrVersionIncompatible
|
|
|
|
}
|
|
|
|
|
|
|
|
// The actual version and expected version are identical.
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// assertBuildTagsEnabled makes sure all required build tags are set.
|
|
|
|
func assertBuildTagsEnabled(actual *verrpc.Version,
|
|
|
|
requiredTags []string) error {
|
|
|
|
|
|
|
|
tagMap := make(map[string]struct{})
|
|
|
|
for _, tag := range actual.BuildTags {
|
|
|
|
tagMap[tag] = struct{}{}
|
|
|
|
}
|
|
|
|
for _, required := range requiredTags {
|
|
|
|
if _, ok := tagMap[required]; !ok {
|
|
|
|
return ErrBuildTagsMissing
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// All tags found.
|
|
|
|
return nil
|
2020-04-22 12:12:17 +00:00
|
|
|
}
|
|
|
|
|
2019-03-06 20:13:50 +00:00
|
|
|
var (
|
|
|
|
defaultRPCPort = "10009"
|
|
|
|
defaultLndDir = btcutil.AppDataDir("lnd", false)
|
|
|
|
defaultTLSCertFilename = "tls.cert"
|
2019-04-17 02:11:34 +00:00
|
|
|
defaultTLSCertPath = filepath.Join(
|
|
|
|
defaultLndDir, defaultTLSCertFilename,
|
|
|
|
)
|
|
|
|
defaultDataDir = "data"
|
|
|
|
defaultChainSubDir = "chain"
|
|
|
|
|
|
|
|
defaultAdminMacaroonFilename = "admin.macaroon"
|
|
|
|
defaultInvoiceMacaroonFilename = "invoices.macaroon"
|
|
|
|
defaultChainMacaroonFilename = "chainnotifier.macaroon"
|
|
|
|
defaultWalletKitMacaroonFilename = "walletkit.macaroon"
|
2019-03-25 09:31:03 +00:00
|
|
|
defaultRouterMacaroonFilename = "router.macaroon"
|
2019-04-17 02:11:34 +00:00
|
|
|
defaultSignerFilename = "signer.macaroon"
|
2020-04-22 12:12:17 +00:00
|
|
|
defaultReadonlyFilename = "readonly.macaroon"
|
2019-05-21 23:57:04 +00:00
|
|
|
|
|
|
|
// maxMsgRecvSize is the largest gRPC message our client will receive.
|
2019-11-15 15:29:20 +00:00
|
|
|
// We set this to 200MiB.
|
|
|
|
maxMsgRecvSize = grpc.MaxCallRecvMsgSize(1 * 1024 * 1024 * 200)
|
2019-03-06 20:13:50 +00:00
|
|
|
)
|
|
|
|
|
2020-04-22 12:29:31 +00:00
|
|
|
func getClientConn(cfg *LndServicesConfig) (*grpc.ClientConn, error) {
|
2019-03-06 20:13:50 +00:00
|
|
|
|
|
|
|
// Load the specified TLS certificate and build transport credentials
|
|
|
|
// with it.
|
2020-04-22 12:29:31 +00:00
|
|
|
tlsPath := cfg.TLSPath
|
2019-03-06 20:13:50 +00:00
|
|
|
if tlsPath == "" {
|
|
|
|
tlsPath = defaultTLSCertPath
|
|
|
|
}
|
|
|
|
|
|
|
|
creds, err := credentials.NewClientTLSFromFile(tlsPath, "")
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create a dial options array.
|
|
|
|
opts := []grpc.DialOption{
|
|
|
|
grpc.WithTransportCredentials(creds),
|
2020-01-03 13:01:31 +00:00
|
|
|
|
|
|
|
// Use a custom dialer, to allow connections to unix sockets,
|
|
|
|
// in-memory listeners etc, and not just TCP addresses.
|
2020-04-22 12:29:31 +00:00
|
|
|
grpc.WithContextDialer(cfg.Dialer),
|
2019-03-06 20:13:50 +00:00
|
|
|
}
|
|
|
|
|
2020-04-22 12:29:31 +00:00
|
|
|
conn, err := grpc.Dial(cfg.LndAddress, opts...)
|
2019-03-06 20:13:50 +00:00
|
|
|
if err != nil {
|
2020-04-22 12:29:31 +00:00
|
|
|
return nil, fmt.Errorf("unable to connect to RPC server: %v",
|
|
|
|
err)
|
2019-03-06 20:13:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return conn, nil
|
|
|
|
}
|