From 187bd29d2d42b85f621973b50780afa42bf7185c Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Thu, 24 Jan 2019 14:51:04 +0100 Subject: [PATCH 1/9] gitignore: add mobile/build --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 9753fdfe..48efdd2a 100644 --- a/.gitignore +++ b/.gitignore @@ -43,6 +43,10 @@ cmd/cmd cmd/lncli/lncli +# Files from mobile build. +mobile/build +mobile/*_generated.go + # vim *.swp From 2562fdbddaadae369dd43c546e90cc315b421106 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Tue, 9 Jul 2019 11:09:19 +0200 Subject: [PATCH 2/9] lnd+rpcserver: extract listener setup into closure --- lnd.go | 102 +++++++++++++++++++++++++++++++++++++-------------- rpcserver.go | 56 ++++++++++++++-------------- 2 files changed, 103 insertions(+), 55 deletions(-) diff --git a/lnd.go b/lnd.go index ec21f4a9..d550407a 100644 --- a/lnd.go +++ b/lnd.go @@ -93,6 +93,13 @@ var ( } ) +// rpcListeners is a function type used for closures that fetches a set of RPC +// listeners for the current configuration, and the GRPC server options to use +// with these listeners. If no custom listeners are present, this should return +// normal listeners from the RPC endpoints defined in the config, and server +// options specifying TLS. +type rpcListeners func() ([]net.Listener, func(), []grpc.ServerOption, error) + // Main is the true entry point for lnd. This function is required since defers // created in the top-level scope of a main method aren't executed if os.Exit() // is called. @@ -240,13 +247,49 @@ func Main() error { // this information. walletInitParams.Birthday = time.Now() + // getListeners is a closure that creates listeners from the + // RPCListeners defined in the config. It also returns a cleanup + // closure and the server options to use for the GRPC server. + getListeners := func() ([]net.Listener, func(), []grpc.ServerOption, + error) { + + var grpcListeners []net.Listener + for _, grpcEndpoint := range cfg.RPCListeners { + // Start a gRPC server listening for HTTP/2 + // connections. + lis, err := lncfg.ListenOnAddress(grpcEndpoint) + if err != nil { + ltndLog.Errorf("unable to listen on %s", + grpcEndpoint) + return nil, nil, nil, err + } + grpcListeners = append(grpcListeners, lis) + } + + cleanup := func() { + for _, lis := range grpcListeners { + lis.Close() + } + } + return grpcListeners, cleanup, serverOpts, nil + } + + // walletUnlockerListeners is a closure we'll hand to the wallet + // unlocker, that will be called when it needs listeners for its GPRC + // server. + walletUnlockerListeners := func() ([]net.Listener, func(), + []grpc.ServerOption, error) { + + return getListeners() + } + // We wait until the user provides a password over RPC. In case lnd is // started with the --noseedbackup flag, we use the default password // for wallet encryption. if !cfg.NoSeedBackup { params, err := waitForWalletPassword( - cfg.RPCListeners, cfg.RESTListeners, serverOpts, - restDialOpts, restProxyDest, tlsCfg, + cfg.RESTListeners, restDialOpts, restProxyDest, tlsCfg, + walletUnlockerListeners, ) if err != nil { err := fmt.Errorf("Unable to set up wallet password "+ @@ -457,12 +500,20 @@ func Main() error { } defer atplManager.Stop() + // rpcListeners is a closure we'll hand to the rpc server, that will be + // called when it needs listeners for its GPRC server. + rpcListeners := func() ([]net.Listener, func(), []grpc.ServerOption, + error) { + + return getListeners() + } + // Initialize, and register our implementation of the gRPC interface // exported by the rpcServer. rpcServer, err := newRPCServer( - server, macaroonService, cfg.SubRPCServers, serverOpts, - restDialOpts, restProxyDest, atplManager, server.invoices, - tower, tlsCfg, + server, macaroonService, cfg.SubRPCServers, restDialOpts, + restProxyDest, atplManager, server.invoices, tower, tlsCfg, + rpcListeners, ) if err != nil { err := fmt.Errorf("Unable to create RPC server: %v", err) @@ -880,9 +931,18 @@ type WalletUnlockParams struct { // waitForWalletPassword will spin up gRPC and REST endpoints for the // WalletUnlocker server, and block until a password is provided by // the user to this RPC server. -func waitForWalletPassword(grpcEndpoints, restEndpoints []net.Addr, - serverOpts []grpc.ServerOption, restDialOpts []grpc.DialOption, - restProxyDest string, tlsConf *tls.Config) (*WalletUnlockParams, error) { +func waitForWalletPassword(restEndpoints []net.Addr, + restDialOpts []grpc.DialOption, restProxyDest string, + tlsConf *tls.Config, getListeners rpcListeners) ( + *WalletUnlockParams, error) { + + // Start a gRPC server listening for HTTP/2 connections, solely used + // for getting the encryption password from the client. + listeners, cleanup, serverOpts, err := getListeners() + if err != nil { + return nil, err + } + defer cleanup() // Set up a new PasswordService, which will listen for passwords // provided over RPC. @@ -911,28 +971,14 @@ func waitForWalletPassword(grpcEndpoints, restEndpoints []net.Addr, // password is the last thing to be printed to the console. var wg sync.WaitGroup - for _, grpcEndpoint := range grpcEndpoints { - // Start a gRPC server listening for HTTP/2 connections, solely - // used for getting the encryption password from the client. - lis, err := lncfg.ListenOnAddress(grpcEndpoint) - if err != nil { - ltndLog.Errorf( - "password RPC server unable to listen on %s", - grpcEndpoint, - ) - return nil, err - } - defer lis.Close() - + for _, lis := range listeners { wg.Add(1) - go func() { - rpcsLog.Infof( - "password RPC server listening on %s", - lis.Addr(), - ) + go func(lis net.Listener) { + rpcsLog.Infof("password RPC server listening on %s", + lis.Addr()) wg.Done() grpcServer.Serve(lis) - }() + }(lis) } // Start a REST proxy for our gRPC server above. @@ -942,7 +988,7 @@ func waitForWalletPassword(grpcEndpoints, restEndpoints []net.Addr, mux := proxy.NewServeMux() - err := lnrpc.RegisterWalletUnlockerHandlerFromEndpoint( + err = lnrpc.RegisterWalletUnlockerHandlerFromEndpoint( ctx, mux, restProxyDest, restDialOpts, ) if err != nil { diff --git a/rpcserver.go b/rpcserver.go index d362bbcc..e11a13f4 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -8,6 +8,7 @@ import ( "fmt" "io" "math" + "net" "net/http" "sort" "strings" @@ -409,6 +410,11 @@ type rpcServer struct { // requests from. grpcServer *grpc.Server + // listeners is a list of listeners to use when starting the grpc + // server. We make it configurable such that the grpc server can listen + // on custom interfaces. + listeners []net.Listener + // listenerCleanUp are a set of closures functions that will allow this // main RPC server to clean up all the listening socket created for the // server. @@ -442,10 +448,10 @@ var _ lnrpc.LightningServer = (*rpcServer)(nil) // base level options passed to the grPC server. This typically includes things // like requiring TLS, etc. func newRPCServer(s *server, macService *macaroons.Service, - subServerCgs *subRPCServerConfigs, serverOpts []grpc.ServerOption, - restDialOpts []grpc.DialOption, restProxyDest string, - atpl *autopilot.Manager, invoiceRegistry *invoices.InvoiceRegistry, - tower *watchtower.Standalone, tlsCfg *tls.Config) (*rpcServer, error) { + subServerCgs *subRPCServerConfigs, restDialOpts []grpc.DialOption, + restProxyDest string, atpl *autopilot.Manager, + invoiceRegistry *invoices.InvoiceRegistry, tower *watchtower.Standalone, + tlsCfg *tls.Config, getListeners rpcListeners) (*rpcServer, error) { // Set up router rpc backend. channelGraph := s.chanDB.ChannelGraph() @@ -570,6 +576,12 @@ func newRPCServer(s *server, macService *macaroons.Service, strmInterceptors, errorLogStreamServerInterceptor(rpcsLog), ) + // Get the listeners and server options to use for this rpc server. + listeners, cleanup, serverOpts, err := getListeners() + if err != nil { + return nil, err + } + // If any interceptors have been set up, add them to the server options. if len(unaryInterceptors) != 0 && len(strmInterceptors) != 0 { chainedUnary := grpc_middleware.WithUnaryServerChain( @@ -585,14 +597,16 @@ func newRPCServer(s *server, macService *macaroons.Service, // gRPC server, and register the main lnrpc server along side. grpcServer := grpc.NewServer(serverOpts...) rootRPCServer := &rpcServer{ - restDialOpts: restDialOpts, - restProxyDest: restProxyDest, - subServers: subServers, - tlsCfg: tlsCfg, - grpcServer: grpcServer, - server: s, - routerBackend: routerBackend, - quit: make(chan struct{}, 1), + restDialOpts: restDialOpts, + listeners: listeners, + listenerCleanUp: []func(){cleanup}, + restProxyDest: restProxyDest, + subServers: subServers, + tlsCfg: tlsCfg, + grpcServer: grpcServer, + server: s, + routerBackend: routerBackend, + quit: make(chan struct{}, 1), } lnrpc.RegisterLightningServer(grpcServer, rootRPCServer) @@ -632,23 +646,11 @@ func (r *rpcServer) Start() error { // With all the sub-servers started, we'll spin up the listeners for // the main RPC server itself. - for _, listener := range cfg.RPCListeners { - lis, err := lncfg.ListenOnAddress(listener) - if err != nil { - ltndLog.Errorf( - "RPC server unable to listen on %s", listener, - ) - return err - } - - r.listenerCleanUp = append(r.listenerCleanUp, func() { - lis.Close() - }) - - go func() { + for _, lis := range r.listeners { + go func(lis net.Listener) { rpcsLog.Infof("RPC server listening on %s", lis.Addr()) r.grpcServer.Serve(lis) - }() + }(lis) } // If Prometheus monitoring is enabled, start the Prometheus exporter. From fa21601d070d633c9b609da09ecf93eb2402afb7 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Tue, 9 Jul 2019 14:04:51 +0200 Subject: [PATCH 3/9] lnd+cmd/lnd/main: add ListenerCfg to Main ListenerCfg allows passing custom listeners to the main method, to be used for the wallet unlocker and rpc server. If these are set these will be used instead of the regular RPC listeners. --- cmd/lnd/main.go | 2 +- lnd.go | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/cmd/lnd/main.go b/cmd/lnd/main.go index 177fb67d..3448b77a 100644 --- a/cmd/lnd/main.go +++ b/cmd/lnd/main.go @@ -11,7 +11,7 @@ import ( func main() { // Call the "real" main in a nested manner so the defers will properly // be executed in the case of a graceful shutdown. - if err := lnd.Main(); err != nil { + if err := lnd.Main(lnd.ListenerCfg{}); err != nil { if e, ok := err.(*flags.Error); ok && e.Type == flags.ErrHelp { } else { fmt.Fprintln(os.Stderr, err) diff --git a/lnd.go b/lnd.go index d550407a..982e672b 100644 --- a/lnd.go +++ b/lnd.go @@ -93,6 +93,18 @@ var ( } ) +// ListenerCfg is a wrapper around custom listeners that can be passed to lnd +// when calling its main method. +type ListenerCfg struct { + // WalletUnlocker can be set to the listener to use for the wallet + // unlocker. If nil a regular network listener will be created. + WalletUnlocker net.Listener + + // RPCListener can be set to the listener to use for the RPC server. If + // nil a regular network listener will be created. + RPCListener net.Listener +} + // rpcListeners is a function type used for closures that fetches a set of RPC // listeners for the current configuration, and the GRPC server options to use // with these listeners. If no custom listeners are present, this should return @@ -103,7 +115,7 @@ type rpcListeners func() ([]net.Listener, func(), []grpc.ServerOption, error) // Main is the true entry point for lnd. This function is required since defers // created in the top-level scope of a main method aren't executed if os.Exit() // is called. -func Main() error { +func Main(lisCfg ListenerCfg) error { // Load the configuration, and parse any command line options. This // function will also set up logging properly. loadedConfig, err := loadConfig() @@ -280,6 +292,17 @@ func Main() error { walletUnlockerListeners := func() ([]net.Listener, func(), []grpc.ServerOption, error) { + // If we have chosen to start with a dedicated listener for the + // wallet unlocker, we return it directly, and empty server + // options to deactivate TLS. + // TODO(halseth): any point in adding TLS support for custom + // listeners? + if lisCfg.WalletUnlocker != nil { + return []net.Listener{lisCfg.WalletUnlocker}, func() {}, + []grpc.ServerOption{}, nil + } + + // Otherwise we'll return the regular listeners. return getListeners() } @@ -505,6 +528,17 @@ func Main() error { rpcListeners := func() ([]net.Listener, func(), []grpc.ServerOption, error) { + // If we have chosen to start with a dedicated listener for the + // rpc server, we return it directly, and empty server options + // to deactivate TLS. + // TODO(halseth): any point in adding TLS support for custom + // listeners? + if lisCfg.RPCListener != nil { + return []net.Listener{lisCfg.RPCListener}, func() {}, + []grpc.ServerOption{}, nil + } + + // Otherwise we'll return the regular listeners. return getListeners() } From a5c63786c6cb334d6f5c4be81f2047ae764572b8 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Thu, 24 Jan 2019 14:51:05 +0100 Subject: [PATCH 4/9] make+mobile: define gen_bindings.sh gen_bindings uses falafel to generate Go bindings from the lnrpc protos. --- Makefile | 5 ++++ mobile/gen_bindings.sh | 64 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100755 mobile/gen_bindings.sh diff --git a/Makefile b/Makefile index c5b0489a..e9297654 100644 --- a/Makefile +++ b/Makefile @@ -170,6 +170,10 @@ rpc: @$(call print, "Compiling protos.") cd ./lnrpc; ./gen_protos.sh +mobile-rpc: + @$(call print, "Creating mobile RPC from protos.") + cd ./mobile; ./gen_bindings.sh + clean: @$(call print, "Cleaning source.$(NC)") $(RM) ./lnd-debug ./lncli-debug @@ -199,4 +203,5 @@ clean: lint \ list \ rpc \ + mobile-rpc \ clean diff --git a/mobile/gen_bindings.sh b/mobile/gen_bindings.sh new file mode 100755 index 00000000..1a3488c5 --- /dev/null +++ b/mobile/gen_bindings.sh @@ -0,0 +1,64 @@ +#!/bin/sh + +mkdir -p build + +# Check falafel version. +falafelVersion="0.5" +falafel=$(which falafel) +if [ $falafel ] +then + version=$($falafel -v) + if [ $version != $falafelVersion ] + then + echo "falafel version $falafelVersion required" + exit 1 + fi + echo "Using plugin $falafel $version" +else + echo "falafel not found" + exit 1 +fi + +pkg="lndmobile" +target_pkg="github.com/lightningnetwork/lnd/lnrpc" + +# Generate APIs by passing the parsed protos to the falafel plugin. +opts="package_name=$pkg,target_package=$target_pkg,listeners=lightning=lightningLis walletunlocker=walletUnlockerLis,mem_rpc=1" +protoc -I/usr/local/include -I. \ + -I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \ + --plugin=protoc-gen-custom=$falafel\ + --custom_out=./build \ + --custom_opt="$opts" \ + --proto_path=../lnrpc \ + rpc.proto + +# If prefix=1 is specified, prefix the generated methods with subserver name. +# This must be enabled to support subservers with name conflicts. +use_prefix="0" +if [[ $prefix = "1" ]] +then + echo "Prefixing methods with subserver name" + use_prefix="1" +fi + +# Find all subservers. +for file in ../lnrpc/**/*.proto +do + DIRECTORY=$(dirname ${file}) + tag=$(basename ${DIRECTORY}) + build_tags="// +build $tag" + lis="lightningLis" + + opts="package_name=$pkg,target_package=$target_pkg/$tag,build_tags=$build_tags,api_prefix=$use_prefix,defaultlistener=$lis" + + echo "Generating mobile protos from ${file}, with build tag ${tag}" + + protoc -I/usr/local/include -I. \ + -I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \ + -I../lnrpc \ + --plugin=protoc-gen-custom=$falafel \ + --custom_out=./build \ + --custom_opt="$opts" \ + --proto_path=${DIRECTORY} \ + ${file} +done From 8a92ccbbf4b5ccfca6e84d87b627a434823f4970 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Thu, 24 Jan 2019 14:51:06 +0100 Subject: [PATCH 5/9] mobile/bindings: add mobile bindings --- mobile/bindings.go | 61 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 mobile/bindings.go diff --git a/mobile/bindings.go b/mobile/bindings.go new file mode 100644 index 00000000..9fb79215 --- /dev/null +++ b/mobile/bindings.go @@ -0,0 +1,61 @@ +// +build ios android + +package lndmobile + +import ( + "fmt" + "os" + "strings" + + flags "github.com/jessevdk/go-flags" + "github.com/lightningnetwork/lnd" +) + +// Start starts lnd in a new goroutine. +// +// extraArgs can be used to pass command line arguments to lnd that will +// override what is found in the config file. Example: +// extraArgs = "--bitcoin.testnet --lnddir=\"/tmp/folder name/\" --profile=5050" +func Start(extraArgs string, callback Callback) { + // Split the argument string on "--" to get separated command line + // arguments. + var splitArgs []string + for _, a := range strings.Split(extraArgs, "--") { + if a == "" { + continue + } + // Finally we prefix any non-empty string with --, and trim + // whitespace to mimic the regular command line arguments. + splitArgs = append(splitArgs, strings.TrimSpace("--"+a)) + } + + // Add the extra arguments to os.Args, as that will be parsed during + // startup. + os.Args = append(os.Args, splitArgs...) + + // We call the main method with the custom in-memory listeners called + // by the mobile APIs, such that the grpc server will use these. + cfg := lnd.ListenerCfg{ + WalletUnlocker: walletUnlockerLis, + RPCListener: lightningLis, + } + + // Call the "real" main in a nested manner so the defers will properly + // be executed in the case of a graceful shutdown. + go func() { + if err := lnd.Main(cfg); err != nil { + if e, ok := err.(*flags.Error); ok && + e.Type == flags.ErrHelp { + } else { + fmt.Fprintln(os.Stderr, err) + } + os.Exit(1) + } + }() + + // TODO(halseth): callback when RPC server is actually running. Since + // the RPC server might take a while to start up, the client might + // assume it is ready to accept calls when this callback is sent, while + // it's not. + callback.OnResponse([]byte("started")) +} From 4dcaea1f5d11c51f64433fa2c55c7127b29af386 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Thu, 24 Jan 2019 14:51:06 +0100 Subject: [PATCH 6/9] make: define make ios, make vendor --- Makefile | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Makefile b/Makefile index e9297654..34b09104 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,6 @@ PKG := github.com/lightningnetwork/lnd ESCPKG := github.com\/lightningnetwork\/lnd +MOBILE_PKG := $(PKG)/mobile BTCD_PKG := github.com/btcsuite/btcd GOVERALLS_PKG := github.com/mattn/goveralls @@ -8,11 +9,15 @@ GOACC_PKG := github.com/ory/go-acc GO_BIN := ${GOPATH}/bin BTCD_BIN := $(GO_BIN)/btcd +GOMOBILE_BIN := GO111MODULE=off $(GO_BIN)/gomobile GOVERALLS_BIN := $(GO_BIN)/goveralls LINT_BIN := $(GO_BIN)/golangci-lint GOACC_BIN := $(GO_BIN)/go-acc BTCD_DIR :=${GOPATH}/src/$(BTCD_PKG) +MOBILE_BUILD_DIR :=${GOPATH}/src/$(MOBILE_PKG)/build +IOS_BUILD_DIR := $(MOBILE_BUILD_DIR)/ios +IOS_BUILD := $(IOS_BUILD_DIR)/Lndmobile.framework COMMIT := $(shell git describe --abbrev=40 --dirty) LDFLAGS := -ldflags "-X $(PKG)/build.Commit=$(COMMIT)" @@ -174,6 +179,15 @@ mobile-rpc: @$(call print, "Creating mobile RPC from protos.") cd ./mobile; ./gen_bindings.sh +vendor: + @$(call print, "Re-creating vendor directory.") + rm -r vendor/; GO111MODULE=on go mod vendor + +ios: vendor mobile-rpc + @$(call print, "Building iOS framework ($(IOS_BUILD)).") + mkdir -p $(IOS_BUILD_DIR) + $(GOMOBILE_BIN) bind -target=ios -tags="ios $(DEV_TAGS) autopilotrpc experimental" $(LDFLAGS) -v -o $(IOS_BUILD) $(MOBILE_PKG) + clean: @$(call print, "Cleaning source.$(NC)") $(RM) ./lnd-debug ./lncli-debug @@ -204,4 +218,6 @@ clean: list \ rpc \ mobile-rpc \ + vendor \ + ios \ clean From 3aa9f183953b02edb750058e276983933705e945 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Thu, 24 Jan 2019 14:51:06 +0100 Subject: [PATCH 7/9] make: define make android, make mobile (ios+android) --- Makefile | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Makefile b/Makefile index 34b09104..7703ff42 100644 --- a/Makefile +++ b/Makefile @@ -18,6 +18,8 @@ BTCD_DIR :=${GOPATH}/src/$(BTCD_PKG) MOBILE_BUILD_DIR :=${GOPATH}/src/$(MOBILE_PKG)/build IOS_BUILD_DIR := $(MOBILE_BUILD_DIR)/ios IOS_BUILD := $(IOS_BUILD_DIR)/Lndmobile.framework +ANDROID_BUILD_DIR := $(MOBILE_BUILD_DIR)/android +ANDROID_BUILD := $(ANDROID_BUILD_DIR)/Lndmobile.aar COMMIT := $(shell git describe --abbrev=40 --dirty) LDFLAGS := -ldflags "-X $(PKG)/build.Commit=$(COMMIT)" @@ -188,6 +190,13 @@ ios: vendor mobile-rpc mkdir -p $(IOS_BUILD_DIR) $(GOMOBILE_BIN) bind -target=ios -tags="ios $(DEV_TAGS) autopilotrpc experimental" $(LDFLAGS) -v -o $(IOS_BUILD) $(MOBILE_PKG) +android: vendor mobile-rpc + @$(call print, "Building Android library ($(ANDROID_BUILD)).") + mkdir -p $(ANDROID_BUILD_DIR) + $(GOMOBILE_BIN) bind -target=android -tags="android $(DEV_TAGS) autopilotrpc experimental" $(LDFLAGS) -v -o $(ANDROID_BUILD) $(MOBILE_PKG) + +mobile: ios android + clean: @$(call print, "Cleaning source.$(NC)") $(RM) ./lnd-debug ./lncli-debug @@ -220,4 +229,6 @@ clean: mobile-rpc \ vendor \ ios \ + android \ + mobile \ clean From fef2074c1dec264067ffa00954fdf3e6eb79fabc Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Thu, 24 Jan 2019 14:51:06 +0100 Subject: [PATCH 8/9] mobile: add sample_lnd.conf --- mobile/sample_lnd.conf | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 mobile/sample_lnd.conf diff --git a/mobile/sample_lnd.conf b/mobile/sample_lnd.conf new file mode 100644 index 00000000..008be571 --- /dev/null +++ b/mobile/sample_lnd.conf @@ -0,0 +1,13 @@ +[Application Options] +debuglevel=info +no-macaroons=1 +maxbackoff=2s +nolisten=1 + +[Routing] +routing.assumechanvalid=1 + +[Bitcoin] +bitcoin.active=1 +bitcoin.testnet=1 +bitcoin.node=neutrino From a8cb1c80eb4449d724cb5541d0ab832779137b27 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Tue, 9 Jul 2019 15:36:56 +0200 Subject: [PATCH 9/9] mobile: add README --- mobile/README.md | 55 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 mobile/README.md diff --git a/mobile/README.md b/mobile/README.md new file mode 100644 index 00000000..219fe138 --- /dev/null +++ b/mobile/README.md @@ -0,0 +1,55 @@ +## Building mobile libraries + +### Prerequisites +#### protoc +Install the dependencies for genarating protobuf definitions as stated in [lnrpc docs]( +../lnrpc/README.md#generate-protobuf-definitions) + +#### gomobile +Follow [gomobile](https://github.com/golang/go/wiki/Mobile) in order to intall `gomobile` and dependencies. + +Remember to run `gomobile init` (otherwise the `lnd` build might just hang). + +Note that `gomobile` only supports building projects from `GOPATH` at this point. + +#### falafel +Install [`falafel`](https://github.com/halseth/falafel): +``` +go get -u -v github.com/halseth/falafel +``` + +### Building `lnd` for iOS +``` +make ios +``` + +### Building `lnd` for Android +``` +make android +``` + +`make mobile` will build both iOS and Android libs. + +### Libraries +After the build has succeeded, the libraries will be found in `mobile/build/ios/Lndmobile.framework` and `mobile/build/android/Lndmobile.aar`. Reference your platforms' SDK documentation for how to add the library to your project. + +#### Generating proto definitions for your language. +In order to call the methods in the generated library, the serialized proto for the given RPC call must be provided. Similarly, the response will be a serialized proto. + +In order to generate protobuf definitions for your language of choice, add the proto plugin to the `protoc` invocations found in [`gen_protos.sh`](../lnrpc/gen_protos.sh). For instance to generate protos for Swift, add `--swift_out=.` and run `make rpc`. + +### Options +Similar to lnd, subservers can be conditionally compiled with the build by setting the tags argument: + +``` +make ios tags="routerrpc" +``` + +To support subservers that have APIs with name conflicts, pass the "prefix" flag. This will add the subserver name as a prefix to each method name: + +``` +make ios tags="routerrpc" prefix=1 +``` + +### API docs +TODO(halseth)