diff --git a/.gitignore b/.gitignore index 17833a841..c7078ebdd 100644 --- a/.gitignore +++ b/.gitignore @@ -8,9 +8,13 @@ litcli-debug # MacOS junk .DS_Store +# Files from mobile build. +mobile/build +mobile/*_generated.go + itest/btcd-itest itest/litd-itest itest/lnd-itest itest/itest.test itest/.logs -itest/*.log \ No newline at end of file +itest/*.log diff --git a/Makefile b/Makefile index 070f0860b..b4fe6189e 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,5 @@ PKG := github.com/lightninglabs/lightning-terminal +MOBILE_PKG := $(PKG)/mobile ESCPKG := github.com\/lightninglabs\/lightning-terminal LND_PKG := github.com/lightningnetwork/lnd LOOP_PKG := github.com/lightninglabs/loop @@ -13,6 +14,13 @@ TOOLS_DIR := tools GO_BIN := ${GOPATH}/bin GOACC_BIN := $(GO_BIN)/go-acc GOIMPORTS_BIN := $(GO_BIN)/gosimports +GOMOBILE_BIN := GO111MODULE=off $(GO_BIN)/gomobile + +MOBILE_BUILD_DIR :=${GOPATH}/src/$(MOBILE_PKG)/build +IOS_BUILD_DIR := $(MOBILE_BUILD_DIR)/ios +IOS_BUILD := $(IOS_BUILD_DIR)/Litdmobile.xcframework +ANDROID_BUILD_DIR := $(MOBILE_BUILD_DIR)/android +ANDROID_BUILD := $(ANDROID_BUILD_DIR)/Litdmobile.aar COMMIT := $(shell git describe --abbrev=40 --dirty --tags) COMMIT_HASH := $(shell git rev-parse HEAD) @@ -247,3 +255,36 @@ clean: $(RM) ./litcli-debug $(RM) ./litd-debug $(RM) coverage.txt + +# ============= +# MOBILE +# ============= +mobile-rpc: + @$(call print, "Creating mobile RPC from protos.") + cd ./litrpc; COMPILE_MOBILE=1 SUBSERVER_PREFIX=1 ./gen_protos_docker.sh + +vendor: + @$(call print, "Re-creating vendor directory.") + rm -r vendor/; go mod vendor + +apple: vendor mobile-rpc + @$(call print, "Building iOS and macOS cxframework ($(IOS_BUILD)).") + mkdir -p $(IOS_BUILD_DIR) + $(GOMOBILE_BIN) bind -target=ios,iossimulator,macos -tags="mobile $(RELEASE_LDFLAGS)" -v -o $(IOS_BUILD) $(MOBILE_PKG) + +ios: vendor mobile-rpc + @$(call print, "Building iOS cxframework ($(IOS_BUILD)).") + mkdir -p $(IOS_BUILD_DIR) + $(GOMOBILE_BIN) bind -target=ios,iossimulator -tags="mobile $(RELEASE_LDFLAGS)" -v -o $(IOS_BUILD) $(MOBILE_PKG) + +macos: vendor mobile-rpc + @$(call print, "Building macOS cxframework ($(IOS_BUILD)).") + mkdir -p $(IOS_BUILD_DIR) + $(GOMOBILE_BIN) bind -target=macos -tags="mobile $(RELEASE_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 -androidapi 21 -tags="mobile $(LND_RELEASE_TAGS)" -v -o $(ANDROID_BUILD) $(MOBILE_PKG) + +mobile: ios android diff --git a/cmd/litd/main.go b/cmd/litd/main.go index 7e4f655d4..6cbe19188 100644 --- a/cmd/litd/main.go +++ b/cmd/litd/main.go @@ -11,7 +11,7 @@ import ( // main starts the lightning-terminal application. func main() { - err := terminal.New().Run() + err := terminal.New(nil, nil).Run() var flagErr *flags.Error isFlagErr := errors.As(err, &flagErr) if err != nil && (!isFlagErr || flagErr.Type != flags.ErrHelp) { diff --git a/config.go b/config.go index e62fda99b..09d66d9e6 100644 --- a/config.go +++ b/config.go @@ -161,8 +161,9 @@ type Config struct { LetsEncryptDir string `long:"letsencryptdir" description:"The directory where the Let's Encrypt library will store its key and certificate."` LetsEncryptListen string `long:"letsencryptlisten" description:"The IP:port on which LiT will listen for Let's Encrypt challenges. Let's Encrypt will always try to contact on port 80. Often non-root processes are not allowed to bind to ports lower than 1024. This configuration option allows a different port to be used, but must be used in combination with port forwarding from port 80. This configuration can also be used to specify another IP address to listen on, for example an IPv6 address."` - TLSCertPath string `long:"tlscertpath" description:"Path to write the self signed TLS certificate for LiT's RPC and REST proxy service (if Let's Encrypt is not used). This only applies to the HTTPSListen port."` - TLSKeyPath string `long:"tlskeypath" description:"Path to write the self signed TLS private key for LiT's RPC and REST proxy service (if Let's Encrypt is not used). This only applies to the HTTPSListen port."` + TLSCertPath string `long:"tlscertpath" description:"Path to write the self signed TLS certificate for LiT's RPC and REST proxy service (if Let's Encrypt is not used). This only applies to the HTTPSListen port."` + TLSKeyPath string `long:"tlskeypath" description:"Path to write the self signed TLS private key for LiT's RPC and REST proxy service (if Let's Encrypt is not used). This only applies to the HTTPSListen port."` + TLSDisableAutofill bool `long:"tlsdisableautofill" description:"Do not include the interface IPs or the system hostname in TLS certificate"` LitDir string `long:"lit-dir" description:"The main directory where LiT looks for its configuration file. If LiT is running in 'remote' lnd mode, this is also the directory where the TLS certificates and log files are stored by default."` ConfigFile string `long:"configfile" description:"Path to LiT's configuration file."` @@ -826,13 +827,15 @@ func buildTLSConfigForHttp2(config *Config) (*tls.Config, error) { } else { tlsCertPath := config.TLSCertPath tlsKeyPath := config.TLSKeyPath + tlsDisableAutoFill := config.TLSDisableAutofill if !lnrpc.FileExists(tlsCertPath) && !lnrpc.FileExists(tlsKeyPath) { + //TODO(kevin): make this a config option, not a hardcoded flag certBytes, keyBytes, err := cert.GenCertPair( defaultSelfSignedCertOrganization, nil, nil, - false, DefaultAutogenValidity, + tlsDisableAutoFill, DefaultAutogenValidity, ) if err != nil { return nil, fmt.Errorf("failed creating "+ diff --git a/litrpc/Dockerfile b/litrpc/Dockerfile index b2cf12b2e..f2e01a667 100644 --- a/litrpc/Dockerfile +++ b/litrpc/Dockerfile @@ -19,6 +19,7 @@ RUN cd /tmp \ && go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@${PROTOC_GEN_GO_GRPC_VERSION} \ && go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@${GRPC_GATEWAY_VERSION} \ && go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@${GRPC_GATEWAY_VERSION} \ + && go install golang.org/x/tools/cmd/goimports@v0.1.7 \ && go install github.com/lightninglabs/falafel@${FALAFEL_VERSION} WORKDIR /build diff --git a/litrpc/gen_protos.sh b/litrpc/gen_protos.sh index 06734e674..067d74507 100755 --- a/litrpc/gen_protos.sh +++ b/litrpc/gen_protos.sh @@ -59,4 +59,10 @@ popd pushd autopilotserverrpc format generate no-rest -popd \ No newline at end of file +popd + +if [[ "$COMPILE_MOBILE" == "1" ]]; then + pushd mobile + ./gen_bindings.sh $FALAFEL_VERSION + popd +fi \ No newline at end of file diff --git a/litrpc/gen_protos_docker.sh b/litrpc/gen_protos_docker.sh index 0f755c2fd..f351f3232 100755 --- a/litrpc/gen_protos_docker.sh +++ b/litrpc/gen_protos_docker.sh @@ -19,5 +19,7 @@ docker run \ --rm \ --user $UID:$UID \ -e UID=$UID \ + -e COMPILE_MOBILE \ + -e SUBSERVER_PREFIX \ -v "$DIR/../:/build" \ lit-protobuf-builder diff --git a/mobile/README.md b/mobile/README.md new file mode 100644 index 000000000..c57eb5290 --- /dev/null +++ b/mobile/README.md @@ -0,0 +1,239 @@ +# Building mobile libraries + +## Prerequisites + +To build for iOS, you need to run macOS with either +[Command Line Tools](https://developer.apple.com/download/all/?q=command%20line%20tools) +or [Xcode](https://apps.apple.com/app/xcode/id497799835) installed. + +To build for Android, you need either +[Android Studio](https://developer.android.com/studio) or +[Command Line Tools](https://developer.android.com/studio#downloads) installed, which in turn must be used to install [Android NDK](https://developer.android.com/ndk/). + + +### Go and Go mobile + +First, follow the instructions to [install Go](https://github.com/lightningnetwork/lnd/blob/master/docs/INSTALL.md#building-a-development-version-from-source). + +Then, install [Go mobile](https://github.com/golang/go/wiki/Mobile) and +initialize it: + +```shell +⛰ go install golang.org/x/mobile/cmd/gomobile@latest +⛰ go mod download golang.org/x/mobile +⛰ gomobile init +``` + +### Docker + +Install and run [Docker](https://www.docker.com/products/docker-desktop). + +### Make + +Check that `make` is available by running the following command without errors: + +```shell +⛰ make --version +``` + +## Building the libraries + +Note that `gomobile` only supports building projects from `$GOPATH` at this +point. However, with the introduction of Go modules, the source code files are +no longer installed there by default. + +To be able to do so, we must turn off module and using the now deprecated +`go get` command before turning modules back on again. + +```shell +⛰ go env -w GO111MODULE="off" +⛰ go get github.com/lightninglabs/lightning-terminal +⛰ go get golang.org/x/mobile/bind +⛰ go env -w GO111MODULE="on" +``` + +Finally, let’s change directory to the newly created lightning-terminal folder inside `$GOPATH`: + +```shell +⛰ cd $GOPATH/src/github.com/lightninglabs/lightning-terminal +``` + +It is not recommended building from the master branch for mainnet. To checkout +the latest tagged release of Lightning Terminal, run + +```shell +⛰ git checkout $(git describe --match "v[0-9]*" --abbrev=0) +``` + +### iOS + +```shell +⛰ make ios +``` + +The Xcode framework file will be found in `mobile/build/ios/Litdmobile.xcframework`. + +### Android + +```shell +⛰ make android +``` + +The AAR library file will be found in `mobile/build/android/Litdmobile.aar`. + +--- +Tip: `make mobile` will build both iOS and Android libraries. + +--- + +## Generating proto definitions + +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. + +### iOS + +In order to generate protobuf definitions for iOS, add `--swift_out=.` to the +first `protoc` invocation found in [ `gen_protos.sh` ](../lnrpc/gen_protos.sh). + +Then, some changes to [Dockerfile](../lnrpc/Dockerfile) need to be done in +order to use the [Swift protobuf](https://github.com/apple/swift-protobuf) +plugin with protoc: + +1. Replace the base image with `FROM swift:focal` so that Swift can be used. +2. `clang-format='1:7.0*'` is unavailable in Ubuntu Focal. Change that to +`clang-format='1:10.0*'`. +3. On the next line, install Go and set the environment variables by adding the +following commands: + +``` +RUN apt-get install -y wget \ + && wget -c https://golang.org/dl/go1.17.6.linux-amd64.tar.gz -O - \ + | tar -xz -C /usr/local +ENV GOPATH=/go +ENV PATH=$PATH:/usr/local/go/bin:/go/bin +``` + +4. At the end of the file, just above `CMD`, add the following `RUN` command. +This will download and compile the latest tagged release of Swift protobuf. + +``` +RUN git clone https://github.com/apple/swift-protobuf.git \ +&& cd swift-protobuf \ +&& git checkout $(git describe --tags --abbrev=0) \ +&& swift build -c release \ +&& mv .build/release/protoc-gen-swift /bin +``` + +Finally, run `make rpc`. + +Tip: The generated Swift files will be found in various folders. If you’d like +to move them to the same folder as the framework file, run + +```shell +⛰ find . -name "*.swift" -print0 | xargs -0 -I {} mv {} mobile/build/ios +``` + +`Litdmobile.xcframework` and all Swift files should now be added to your Xcode +project. You will also need to add [Swift Protobuf](https://github.com/apple/swift-protobuf) +to your project to support the generated code. + +### Android + +#### First option: + +In order to generate protobuf definitions for Android, add `--java_out=.` + +to the first `protoc` invocation found in +[ `gen_protos.sh` ](../lnrpc/gen_protos.sh). Then, run `make rpc`. + + +#### Second option (preferable): + +- You have to install the profobuf plugin to your Android application. +Please, follow this link https://github.com/google/protobuf-gradle-plugin. +- Add this line to your `app build.gradle` file. +```shell +classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.17" +``` +- Create a `proto` folder under the `main` folder. + +![proto_folder](docs/proto_folder.png) + +- Add `aar` file to libs folder. + +- After that add these lines to your `module's` `build.gradle` file: + +```shell +plugins { + id "com.google.protobuf" +} + +android { + sourceSets { + main { + proto { + + } + } + } +} + +dependencies { + implementation fileTree(dir: "libs", include: ["*.jar"]) + implementation "com.google.protobuf:protobuf-javalite:${rootProject.ext.javalite_version}" +} + +protobuf { + protoc { + artifact = "com.google.protobuf:protoc:${rootProject.ext.protoc_version}" + } + generateProtoTasks { + all().each { task -> + task.builtins { + java { + option "lite" + } + } + } + } +} +``` +- Then, copy all the proto files from `lnd/lnrpc` to your `proto` folder, saving the structure. +- Build the project and wait until you see the generated Java proto files in the `build` folder. + + +--- +*Note:* + +If Android Studio tells you that the `aar` file cannot be included into the `app-bundle`, this is a workaround: + +1. Create a separate gradle module +2. Remove everything from there and leave only `aar` and `build.gradle`. + +![separate_gradle_module](docs/separate_gradle_module.png) + +3. Gradle file should contain only these lines: + +```shell +configurations.maybeCreate("default") +artifacts.add("default", file('Litdmobile.aar')) +``` + +4. In `dependencies` add this line instead of depending on `libs` folder: +```shell +implementation project(":litdmobile", { "default" }) +``` +--- + +## Calling the API + +In LND v0.15+ all API methods have prefixed the generated methods with the subserver name. This is required to support subservers with name conflicts. + +eg. `QueryScores` is now `AutopilotQueryScores`. `GetBlockHeader` is now `NeutrinoKitGetBlockHeader`. + +## API docs + +- [LND gRPC API Reference](https://api.lightning.community) +- [LND Builder’s Guide](https://docs.lightning.engineering) diff --git a/mobile/bindings.go b/mobile/bindings.go new file mode 100644 index 000000000..f82c36cf2 --- /dev/null +++ b/mobile/bindings.go @@ -0,0 +1,124 @@ +//go:build mobile +// +build mobile + +package litdmobile + +import ( + "errors" + "fmt" + "os" + "strings" + "sync/atomic" + + "github.com/jessevdk/go-flags" + terminal "github.com/lightninglabs/lightning-terminal" + "github.com/lightningnetwork/lnd" + "google.golang.org/grpc" +) + +// litdStarted will be used atomically to ensure only a single lnd instance is +// attempted to be started at once. +var litdStarted int32 + +// 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" +// +// The rpcReady is called lnd is ready to accept RPC calls. +// +// NOTE: On mobile platforms the '--lnddir` argument should be set to the +// current app directory in order to ensure lnd has the permissions needed to +// write to it. +func Start(extraArgs string, rpcReady Callback) { + // We only support a single litd instance at a time (singleton) for now, + // so we make sure to return immediately if it has already been + // started. + if !atomic.CompareAndSwapInt32(&litdStarted, 0, 1) { + err := errors.New("litd already started") + rpcReady.OnError(err) + return + } + + // (Re-)initialize the in-mem gRPC listeners we're going to give to lnd. + // This is required each time lnd is started, because when lnd shuts + // down, the in-mem listeners are closed. + RecreateListeners() + + var splitArgs []string + for _, a := range strings.Split(extraArgs, "--") { + // Trim any whitespace space, and ignore empty params. + a := strings.TrimSpace(a) + if a == "" { + continue + } + + // Finally we prefix any non-empty string with -- to mimic the + // regular command line arguments. + splitArgs = append(splitArgs, "--"+a) + } + + // Add the extra arguments to os.Args, as that will be parsed in + // LoadConfig below. + os.Args = append(os.Args, splitArgs...) + + var ( + rpcListening = make(chan struct{}) + term *terminal.LightningTerminal + ) + go func() { + term = terminal.New(lightningLis, rpcListening) + err := term.Run() + if err != nil { + if e, ok := err.(*flags.Error); ok && + e.Type == flags.ErrHelp { + } else { + fmt.Fprintln(os.Stderr, err) + } + rpcReady.OnError(err) + return + } + }() + + // By this point, we should be started, call rpcReady + go func() { + select { + case <-rpcListening: + cfg := term.GetConfig() + authCfg := &lnd.Config{ + TLSCertPath: cfg.TLSCertPath, + NoMacaroons: false, + AdminMacPath: cfg.Lnd.AdminMacPath, + } + proxyCfg := &lnd.Config{} + // By default we'll apply the admin auth options, which will include + // macaroons. + setDefaultDialOption( + func() ([]grpc.DialOption, error) { + return lnd.AdminAuthOptions(authCfg, false) + }, + ) + // For WalletUnlocker, StateService, and Proxy, the macaroons might not be + // available yet when called, so we use a more restricted set of + // options that don't include them. + setWalletUnlockerDialOption( + func() ([]grpc.DialOption, error) { + return lnd.AdminAuthOptions(authCfg, true) + }, + ) + setProxyDialOption( + func() ([]grpc.DialOption, error) { + return lnd.AdminAuthOptions(proxyCfg, true) + }, + ) + setStateDialOption( + func() ([]grpc.DialOption, error) { + return lnd.AdminAuthOptions(authCfg, true) + }, + ) + } + rpcReady.OnResponse([]byte{}) + }() +} diff --git a/mobile/docs/proto_folder.png b/mobile/docs/proto_folder.png new file mode 100644 index 000000000..43f0e1570 Binary files /dev/null and b/mobile/docs/proto_folder.png differ diff --git a/mobile/docs/separate_gradle_module.png b/mobile/docs/separate_gradle_module.png new file mode 100644 index 000000000..cc884ee3b Binary files /dev/null and b/mobile/docs/separate_gradle_module.png differ diff --git a/mobile/gen_bindings.sh b/mobile/gen_bindings.sh new file mode 100755 index 000000000..9ae160225 --- /dev/null +++ b/mobile/gen_bindings.sh @@ -0,0 +1,282 @@ +#!/bin/sh + +mkdir -p build + +# Check falafel version. +falafelVersion=$1 +if [ -z $falafelVersion ] +then + echo "falafel version not set" + exit 1 +fi + +falafel=$(which falafel) +if [ $falafel ] +then + version="v$($falafel -v)" + if [ $version != $falafelVersion ] + then + echo "falafel version $falafelVersion required, had $version" + exit 1 + fi + echo "Using plugin $falafel $version" +else + echo "falafel not found" + exit 1 +fi + +# Name of the package for the generated APIs. +pkg="litdmobile" + +# The package where the protobuf definitions originally are found. +litd_target_pkg="github.com/lightninglabs/lightning-terminal/litrpc" + +lnd_target_pkg="github.com/lightningnetwork/lnd/lnrpc" +autopilot_target_pkg="github.com/lightningnetwork/lnd/lnrpc/autopilotrpc" +chain_target_pkg="github.com/lightningnetwork/lnd/lnrpc/chainrpc" +invoices_target_pkg="github.com/lightningnetwork/lnd/lnrpc/invoicesrpc" +neutrino_target_pkg="github.com/lightningnetwork/lnd/lnrpc/neutrinorpc" +router_target_pkg="github.com/lightningnetwork/lnd/lnrpc/routerrpc" +signer_target_pkg="github.com/lightningnetwork/lnd/lnrpc/signrpc" +wallet_target_pkg="github.com/lightningnetwork/lnd/lnrpc/walletrpc" +watchtower_target_pkg="github.com/lightningnetwork/lnd/lnrpc/watchtowerrpc" +watchtower_client_target_pkg="github.com/lightningnetwork/lnd/lnrpc/wtclientrpc" + +loop_target_pkg="github.com/lightninglabs/loop/looprpc" +pool_target_pkg="github.com/lightninglabs/pool/poolrpc" + +tapd_target_pkg="github.com/lightninglabs/taproot-assets/taprpc" +assetwallet_target_pkg="github.com/lightninglabs/taproot-assets/taprpc/assetwalletrpc" + +# A mapping from grpc service to name of the custom listeners. The grpc server +# must be configured to listen on these. +listeners="accounts=lightningLis sessions=lightningLis proxy=lightningLis lightning=lightningLis walletunlocker=lightningLis state=lightningLis autopilot=lightningLis chainnotifier=lightningLis invoices=lightningLis neutrinokit=lightningLis peers=lightningLis router=lightningLis signer=lightningLis versioner=lightningLis walletkit=lightningLis watchtower=lightningLis watchtowerclient=lightningLis swapclient=lightningLis swapserver=lightningLis trader=lightningLis channelauctioneer=lightningLis taprootassets=lightningLis assetwallet=lightningLis" + +# Set to 1 to create boiler plate grpc client code and listeners. If more than +# one proto file is being parsed, it should only be done once. +mem_rpc=1 + +LITD_PROTOS="lit-accounts.proto lit-sessions.proto proxy.proto" + +LND_PROTOS="lnd.proto stateservice.proto walletunlocker.proto" +AUTOPILOT_PROTOS="autopilotrpc/autopilot.proto" +CHAIN_PROTOS="chainrpc/chainnotifier.proto" +INVOICES_PROTOS="invoicesrpc/invoices.proto" +NEUTRINO_PROTOS="neutrinorpc/neutrino.proto" +ROUTER_PROTOS="routerrpc/router.proto" +SIGNER_PROTOS="signrpc/signer.proto" +WALLET_PROTOS="walletrpc/walletkit.proto" +WATCHTOWER_PROTOS="watchtowerrpc/watchtower.proto" +WATCHTOWER_CLIENT_PROTOS="wtclientrpc/wtclient.proto" + +LOOP_PROTOS="loop.proto swapserverrpc/common.proto" + +POOL_PROTOS="trader.proto auctioneerrpc/auctioneer.proto" + +TAPD_PROTOS="taprootassets.proto assetwalletrpc/assetwallet.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 [ "$SUBSERVER_PREFIX" = "1" ] +then + echo "Prefixing methods with subserver name" + use_prefix="1" +fi + +litd_opts="package_name=$pkg,target_package=$litd_target_pkg,api_prefix=$use_prefix,listeners=$listeners,mem_rpc=$mem_rpc" + +lnd_opts="package_name=$pkg,target_package=$lnd_target_pkg,api_prefix=0,listeners=$listeners,mem_rpc=$mem_rpc" +autopilot_opts="package_name=$pkg,target_package=$autopilot_target_pkg,api_prefix=$use_prefix,listeners=$listeners,mem_rpc=$mem_rpc" +chain_opts="package_name=$pkg,target_package=$chain_target_pkg,api_prefix=$use_prefix,listeners=$listeners,mem_rpc=$mem_rpc" +invoices_opts="package_name=$pkg,target_package=$invoices_target_pkg,api_prefix=$use_prefix,listeners=$listeners,mem_rpc=$mem_rpc" +neutrino_opts="package_name=$pkg,target_package=$neutrino_target_pkg,api_prefix=$use_prefix,listeners=$listeners,mem_rpc=$mem_rpc" +router_opts="package_name=$pkg,target_package=$router_target_pkg,api_prefix=$use_prefix,listeners=$listeners,mem_rpc=$mem_rpc" +signer_opts="package_name=$pkg,target_package=$signer_target_pkg,api_prefix=$use_prefix,listeners=$listeners,mem_rpc=$mem_rpc" +wallet_opts="package_name=$pkg,target_package=$wallet_target_pkg,api_prefix=$use_prefix,listeners=$listeners,mem_rpc=$mem_rpc" +watchtower_opts="package_name=$pkg,target_package=$watchtower_target_pkg,api_prefix=$use_prefix,listeners=$listeners,mem_rpc=$mem_rpc" +watchtower_client_opts="package_name=$pkg,target_package=$watchtower_client_target_pkg,api_prefix=$use_prefix,listeners=$listeners,mem_rpc=$mem_rpc" + +loop_opts="package_name=$pkg,target_package=$loop_target_pkg,api_prefix=$use_prefix,listeners=$listeners,mem_rpc=$mem_rpc" +pool_opts="package_name=$pkg,target_package=$pool_target_pkg,api_prefix=$use_prefix,listeners=$listeners,mem_rpc=$mem_rpc" +auctioneer_opts="package_name=$pkg,target_package=$auctioneer_target_pkg,api_prefix=$use_prefix,listeners=$listeners,mem_rpc=$mem_rpc" +tapd_opts="package_name=$pkg,target_package=$tapd_target_pkg,api_prefix=$use_prefix,listeners=$listeners,mem_rpc=$mem_rpc" +assetwallet_opts="package_name=$pkg,target_package=$assetwallet_target_pkg,api_prefix=$use_prefix,listeners=$listeners,mem_rpc=$mem_rpc" + +for file in $LITD_PROTOS; do + echo "Generating mobile protos from ${file}" + + protoc -I/usr/local/include -I. \ + --plugin=protoc-gen-custom=$falafel\ + --custom_out=./build \ + --custom_opt="$litd_opts" \ + --proto_path=../proto \ + "${file}" +done + +for file in $LND_PROTOS; do + echo "Generating mobile protos from ${file}" + + protoc -I/usr/local/include -I. \ + --plugin=protoc-gen-custom=$falafel\ + --custom_out=./build \ + --custom_opt="$lnd_opts" \ + --proto_path=../proto \ + "${file}" +done + +for file in $AUTOPILOT_PROTOS; do + echo "Generating mobile protos from ${file}" + + protoc -I/usr/local/include -I. \ + --plugin=protoc-gen-custom=$falafel\ + --custom_out=./build \ + --custom_opt="$autopilot_opts" \ + --proto_path=../proto \ + "${file}" +done + +for file in $CHAIN_PROTOS; do + echo "Generating mobile protos from ${file}" + + protoc -I/usr/local/include -I. \ + --plugin=protoc-gen-custom=$falafel\ + --custom_out=./build \ + --custom_opt="$chain_opts" \ + --proto_path=../proto \ + "${file}" +done + +for file in $INVOICES_PROTOS; do + echo "Generating mobile protos from ${file}" + + protoc -I/usr/local/include -I. \ + --plugin=protoc-gen-custom=$falafel\ + --custom_out=./build \ + --custom_opt="$invoices_opts" \ + --proto_path=../proto \ + "${file}" +done + +for file in $NEUTRINO_PROTOS; do + echo "Generating mobile protos from ${file}" + + protoc -I/usr/local/include -I. \ + --plugin=protoc-gen-custom=$falafel\ + --custom_out=./build \ + --custom_opt="$neutrino_opts" \ + --proto_path=../proto \ + "${file}" +done + +for file in $ROUTER_PROTOS; do + echo "Generating mobile protos from ${file}" + + protoc -I/usr/local/include -I. \ + --plugin=protoc-gen-custom=$falafel\ + --custom_out=./build \ + --custom_opt="$router_opts" \ + --proto_path=../proto \ + "${file}" +done + +for file in $SIGNER_PROTOS; do + echo "Generating mobile protos from ${file}" + + protoc -I/usr/local/include -I. \ + --plugin=protoc-gen-custom=$falafel\ + --custom_out=./build \ + --custom_opt="$signer_opts" \ + --proto_path=../proto \ + "${file}" +done + +for file in $WALLET_PROTOS; do + echo "Generating mobile protos from ${file}" + + protoc -I/usr/local/include -I. \ + --plugin=protoc-gen-custom=$falafel\ + --custom_out=./build \ + --custom_opt="$wallet_opts" \ + --proto_path=../proto \ + "${file}" +done + +for file in $WATCHTOWER_PROTOS; do + echo "Generating mobile protos from ${file}" + + protoc -I/usr/local/include -I. \ + --plugin=protoc-gen-custom=$falafel\ + --custom_out=./build \ + --custom_opt="$watchtower_opts" \ + --proto_path=../proto \ + "${file}" +done + +for file in $WATCHTOWER_CLIENT_PROTOS; do + echo "Generating mobile protos from ${file}" + + protoc -I/usr/local/include -I. \ + --plugin=protoc-gen-custom=$falafel\ + --custom_out=./build \ + --custom_opt="$watchtower_client_opts" \ + --proto_path=../proto \ + "${file}" +done + +for file in $LOOP_PROTOS; do + echo "Generating mobile protos from ${file}" + + protoc -I/usr/local/include -I. \ + --plugin=protoc-gen-custom=$falafel\ + --custom_out=./build \ + --custom_opt="$loop_opts" \ + --proto_path=../proto \ + "${file}" +done + +for file in $POOL_PROTOS; do + echo "Generating mobile protos from ${file}" + + protoc -I/usr/local/include -I. \ + --plugin=protoc-gen-custom=$falafel\ + --custom_out=./build \ + --custom_opt="$pool_opts" \ + --proto_path=../proto \ + "${file}" +done + +# for file in $TAPD_PROTOS; do +echo "Generating mobile protos from taprootassets.proto" +protoc -I/usr/local/include -I. \ + --plugin=protoc-gen-custom=$falafel\ + --custom_out=./build \ + --custom_opt="$tapd_opts" \ + --proto_path=../proto \ + taprootassets.proto + +echo "Generating mobile protos from assetwalletrpc/assetwallet.proto" +protoc -I/usr/local/include -I. \ + --plugin=protoc-gen-custom=$falafel\ + --custom_out=./build \ + --custom_opt="$assetwallet_opts" \ + --proto_path=../proto \ + assetwalletrpc/assetwallet.proto +# done + +# TODO update protoc command to avoid this replace hack +sed -i '12i "github.com/lightningnetwork/lnd/lnrpc/signrpc"' ./walletkit_api_generated.go +sed -i '12i "github.com/lightninglabs/pool/auctioneerrpc"' ./trader_api_generated.go +sed -i '14i "github.com/lightninglabs/taproot-assets/taprpc/assetwalletrpc"' ./assetwallet_api_generated.go + +trader_replacements="BatchSnapshotRequest BatchSnapshotsRequest" +for call in $trader_replacements; do + echo "Making replacements for trader_api_generated.go: ${call}" + sed -i "s/poolrpc.${call}/auctioneerrpc.${call}/g" ./trader_api_generated.go +done + +echo "Making replacements for channelauctioneer_api_generated.go" +sed -i "s/poolrpc/auctioneerrpc/g" ./channelauctioneer_api_generated.go + +# Run goimports to resolve any dependencies among the sub-servers. +goimports -w ./*_generated.go diff --git a/mobile/go.mod b/mobile/go.mod new file mode 100644 index 000000000..f3e4d6dd9 --- /dev/null +++ b/mobile/go.mod @@ -0,0 +1,3 @@ +module mobile + +go 1.18 diff --git a/mobile/sample_lnd.conf b/mobile/sample_lnd.conf new file mode 100644 index 000000000..3f4cc6c3e --- /dev/null +++ b/mobile/sample_lnd.conf @@ -0,0 +1,14 @@ +[Application Options] +debuglevel=info +maxbackoff=2s +nolisten=1 +norest=1 +tlsdisableautofill=1 + +[Routing] +routing.assumechanvalid=1 + +[Bitcoin] +bitcoin.active=1 +bitcoin.testnet=1 +bitcoin.node=neutrino diff --git a/proto/assetwalletrpc/assetwallet.proto b/proto/assetwalletrpc/assetwallet.proto new file mode 100644 index 000000000..5c6cbc0cf --- /dev/null +++ b/proto/assetwalletrpc/assetwallet.proto @@ -0,0 +1,223 @@ +syntax = "proto3"; + +import "taprootassets.proto"; + +package assetwalletrpc; + +option go_package = "github.com/lightninglabs/taproot-assets/taprpc/assetwalletrpc"; + +service AssetWallet { + /* + FundVirtualPsbt selects inputs from the available asset commitments to fund + a virtual transaction matching the template. + */ + rpc FundVirtualPsbt (FundVirtualPsbtRequest) + returns (FundVirtualPsbtResponse); + + /* + SignVirtualPsbt signs the inputs of a virtual transaction and prepares the + commitments of the inputs and outputs. + */ + rpc SignVirtualPsbt (SignVirtualPsbtRequest) + returns (SignVirtualPsbtResponse); + + /* + AnchorVirtualPsbts merges and then commits multiple virtual transactions in + a single BTC level anchor transaction. + + TODO(guggero): Actually implement accepting and merging multiple + transactions. + */ + rpc AnchorVirtualPsbts (AnchorVirtualPsbtsRequest) + returns (taprpc.SendAssetResponse); + + /* + NextInternalKey derives the next internal key for the given key family and + stores it as an internal key in the database to make sure it is identified + as a local key later on when importing proofs. While an internal key can + also be used as the internal key of a script key, it is recommended to use + the NextScriptKey RPC instead, to make sure the tweaked Taproot output key + is also recognized as a local key. + */ + rpc NextInternalKey (NextInternalKeyRequest) + returns (NextInternalKeyResponse); + + /* + NextScriptKey derives the next script key (and its corresponding internal + key) and stores them both in the database to make sure they are identified + as local keys later on when importing proofs. + */ + rpc NextScriptKey (NextScriptKeyRequest) returns (NextScriptKeyResponse); + + /* + ProveAssetOwnership creates an ownership proof embedded in an asset + transition proof. That ownership proof is a signed virtual transaction + spending the asset with a valid witness to prove the prover owns the keys + that can spend the asset. + */ + rpc ProveAssetOwnership (ProveAssetOwnershipRequest) + returns (ProveAssetOwnershipResponse); + + /* + VerifyAssetOwnership verifies the asset ownership proof embedded in the + given transition proof of an asset and returns true if the proof is valid. + */ + rpc VerifyAssetOwnership (VerifyAssetOwnershipRequest) + returns (VerifyAssetOwnershipResponse); + + /* + RemoveUTXOLease removes the lease/lock/reservation of the given managed + UTXO. + */ + rpc RemoveUTXOLease (RemoveUTXOLeaseRequest) + returns (RemoveUTXOLeaseResponse); +} + +message FundVirtualPsbtRequest { + oneof template { + /* + Use an existing PSBT packet as the template for the funded PSBT. + + TODO(guggero): Actually implement this. We can't use the "reserved" + keyword here because we're in a oneof, so we add the field but implement + it later. + */ + bytes psbt = 1; + + /* + Use the asset outputs and optional asset inputs from this raw template. + */ + TxTemplate raw = 2; + } +} + +message FundVirtualPsbtResponse { + /* + The funded but not yet signed PSBT packet. + */ + bytes funded_psbt = 1; + + /* + The index of the added change output or -1 if no change was left over. + */ + int32 change_output_index = 2; +} + +message TxTemplate { + /* + An optional list of inputs to use. Every input must be an asset UTXO known + to the wallet. The sum of all inputs must be greater than or equal to the + sum of all outputs. + + If no inputs are specified, asset coin selection will be performed instead + and inputs of sufficient value will be added to the resulting PSBT. + */ + repeated PrevId inputs = 1; + + /* + A map of all Taproot Asset addresses mapped to the anchor transaction's + output index that should be sent to. + */ + map recipients = 2; +} + +message PrevId { + /* + The bitcoin anchor output on chain that contains the input asset. + */ + OutPoint outpoint = 1; + + /* + The asset ID of the previous asset tree. + */ + bytes id = 2; + + /* + The tweaked Taproot output key committing to the possible spending + conditions of the asset. + */ + bytes script_key = 3; +} + +message OutPoint { + /* + Raw bytes representing the transaction id. + */ + bytes txid = 1; + + /* + The index of the output on the transaction. + */ + uint32 output_index = 2; +} + +message SignVirtualPsbtRequest { + /* + The PSBT of the virtual transaction that should be signed. The PSBT must + contain all required inputs, outputs, UTXO data and custom fields required + to identify the signing key. + */ + bytes funded_psbt = 1; +} + +message SignVirtualPsbtResponse { + /* + The signed virtual transaction in PSBT format. + */ + bytes signed_psbt = 1; + + /* + The indices of signed inputs. + */ + repeated uint32 signed_inputs = 2; +} + +message AnchorVirtualPsbtsRequest { + /* + The list of virtual transactions that should be merged and committed to in + the BTC level anchor transaction. + */ + repeated bytes virtual_psbts = 1; +} + +message NextInternalKeyRequest { + uint32 key_family = 1; +} + +message NextInternalKeyResponse { + taprpc.KeyDescriptor internal_key = 1; +} + +message NextScriptKeyRequest { + uint32 key_family = 1; +} + +message NextScriptKeyResponse { + taprpc.ScriptKey script_key = 1; +} + +message ProveAssetOwnershipRequest { + bytes asset_id = 1; + + bytes script_key = 2; +} + +message ProveAssetOwnershipResponse { + bytes proof_with_witness = 1; +} + +message VerifyAssetOwnershipRequest { + bytes proof_with_witness = 1; +} + +message VerifyAssetOwnershipResponse { + bool valid_proof = 1; +} + +message RemoveUTXOLeaseRequest { + // The outpoint of the UTXO to remove the lease for. + OutPoint outpoint = 1; +} + +message RemoveUTXOLeaseResponse { +} diff --git a/proto/autopilotrpc/autopilot.proto b/proto/autopilotrpc/autopilot.proto new file mode 100644 index 000000000..67d0f9e38 --- /dev/null +++ b/proto/autopilotrpc/autopilot.proto @@ -0,0 +1,80 @@ +syntax = "proto3"; + +package autopilotrpc; + +option go_package = "github.com/lightningnetwork/lnd/lnrpc/autopilotrpc"; + +// Autopilot is a service that can be used to get information about the current +// state of the daemon's autopilot agent, and also supply it with information +// that can be used when deciding where to open channels. +service Autopilot { + /* + Status returns whether the daemon's autopilot agent is active. + */ + rpc Status (StatusRequest) returns (StatusResponse); + + /* + ModifyStatus is used to modify the status of the autopilot agent, like + enabling or disabling it. + */ + rpc ModifyStatus (ModifyStatusRequest) returns (ModifyStatusResponse); + + /* + QueryScores queries all available autopilot heuristics, in addition to any + active combination of these heruristics, for the scores they would give to + the given nodes. + */ + rpc QueryScores (QueryScoresRequest) returns (QueryScoresResponse); + + /* + SetScores attempts to set the scores used by the running autopilot agent, + if the external scoring heuristic is enabled. + */ + rpc SetScores (SetScoresRequest) returns (SetScoresResponse); +} + +message StatusRequest { +} + +message StatusResponse { + // Indicates whether the autopilot is active or not. + bool active = 1; +} + +message ModifyStatusRequest { + // Whether the autopilot agent should be enabled or not. + bool enable = 1; +} + +message ModifyStatusResponse { +} + +message QueryScoresRequest { + repeated string pubkeys = 1; + + // If set, we will ignore the local channel state when calculating scores. + bool ignore_local_state = 2; +} + +message QueryScoresResponse { + message HeuristicResult { + string heuristic = 1; + map scores = 2; + } + + repeated HeuristicResult results = 1; +} + +message SetScoresRequest { + // The name of the heuristic to provide scores to. + string heuristic = 1; + + /* + A map from hex-encoded public keys to scores. Scores must be in the range + [0.0, 1.0]. + */ + map scores = 2; +} + +message SetScoresResponse { +} diff --git a/proto/chainrpc/chainnotifier.proto b/proto/chainrpc/chainnotifier.proto new file mode 100644 index 000000000..36e66a279 --- /dev/null +++ b/proto/chainrpc/chainnotifier.proto @@ -0,0 +1,200 @@ +syntax = "proto3"; + +package chainrpc; + +option go_package = "github.com/lightningnetwork/lnd/lnrpc/chainrpc"; + +// ChainNotifier is a service that can be used to get information about the +// chain backend by registering notifiers for chain events. +service ChainNotifier { + /* + RegisterConfirmationsNtfn is a synchronous response-streaming RPC that + registers an intent for a client to be notified once a confirmation request + has reached its required number of confirmations on-chain. + + A confirmation request must have a valid output script. It is also possible + to give a transaction ID. If the transaction ID is not set, a notification + is sent once the output script confirms. If the transaction ID is also set, + a notification is sent once the output script confirms in the given + transaction. + */ + rpc RegisterConfirmationsNtfn (ConfRequest) returns (stream ConfEvent); + + /* + RegisterSpendNtfn is a synchronous response-streaming RPC that registers an + intent for a client to be notification once a spend request has been spent + by a transaction that has confirmed on-chain. + + A client can specify whether the spend request should be for a particular + outpoint or for an output script by specifying a zero outpoint. + */ + rpc RegisterSpendNtfn (SpendRequest) returns (stream SpendEvent); + + /* + RegisterBlockEpochNtfn is a synchronous response-streaming RPC that + registers an intent for a client to be notified of blocks in the chain. The + stream will return a hash and height tuple of a block for each new/stale + block in the chain. It is the client's responsibility to determine whether + the tuple returned is for a new or stale block in the chain. + + A client can also request a historical backlog of blocks from a particular + point. This allows clients to be idempotent by ensuring that they do not + missing processing a single block within the chain. + */ + rpc RegisterBlockEpochNtfn (BlockEpoch) returns (stream BlockEpoch); +} + +message ConfRequest { + /* + The transaction hash for which we should request a confirmation notification + for. If set to a hash of all zeros, then the confirmation notification will + be requested for the script instead. + */ + bytes txid = 1; + + /* + An output script within a transaction with the hash above which will be used + by light clients to match block filters. If the transaction hash is set to a + hash of all zeros, then a confirmation notification will be requested for + this script instead. + */ + bytes script = 2; + + /* + The number of desired confirmations the transaction/output script should + reach before dispatching a confirmation notification. + */ + uint32 num_confs = 3; + + /* + The earliest height in the chain for which the transaction/output script + could have been included in a block. This should in most cases be set to the + broadcast height of the transaction/output script. + */ + uint32 height_hint = 4; + + /* + If true, then the block that mines the specified txid/script will be + included in eventual the notification event. + */ + bool include_block = 5; +} + +message ConfDetails { + // The raw bytes of the confirmed transaction. + bytes raw_tx = 1; + + // The hash of the block in which the confirmed transaction was included in. + bytes block_hash = 2; + + // The height of the block in which the confirmed transaction was included + // in. + uint32 block_height = 3; + + // The index of the confirmed transaction within the block. + uint32 tx_index = 4; + + /* + The raw bytes of the block that mined the transaction. Only included if + include_block was set in the request. + */ + bytes raw_block = 5; +} + +message Reorg { + // TODO(wilmer): need to know how the client will use this first. +} + +message ConfEvent { + oneof event { + /* + An event that includes the confirmation details of the request + (txid/ouput script). + */ + ConfDetails conf = 1; + + /* + An event send when the transaction of the request is reorged out of the + chain. + */ + Reorg reorg = 2; + } +} + +message Outpoint { + // The hash of the transaction. + bytes hash = 1; + + // The index of the output within the transaction. + uint32 index = 2; +} + +message SpendRequest { + /* + The outpoint for which we should request a spend notification for. If set to + a zero outpoint, then the spend notification will be requested for the + script instead. A zero or nil outpoint is not supported for Taproot spends + because the output script cannot reliably be computed from the witness alone + and the spent output script is not always available in the rescan context. + So an outpoint must _always_ be specified when registering a spend + notification for a Taproot output. + */ + Outpoint outpoint = 1; + + /* + The output script for the outpoint above. This will be used by light clients + to match block filters. If the outpoint is set to a zero outpoint, then a + spend notification will be requested for this script instead. + */ + bytes script = 2; + + /* + The earliest height in the chain for which the outpoint/output script could + have been spent. This should in most cases be set to the broadcast height of + the outpoint/output script. + */ + uint32 height_hint = 3; + + // TODO(wilmer): extend to support num confs on spending tx. +} + +message SpendDetails { + // The outpoint was that spent. + Outpoint spending_outpoint = 1; + + // The raw bytes of the spending transaction. + bytes raw_spending_tx = 2; + + // The hash of the spending transaction. + bytes spending_tx_hash = 3; + + // The input of the spending transaction that fulfilled the spend request. + uint32 spending_input_index = 4; + + // The height at which the spending transaction was included in a block. + uint32 spending_height = 5; +} + +message SpendEvent { + oneof event { + /* + An event that includes the details of the spending transaction of the + request (outpoint/output script). + */ + SpendDetails spend = 1; + + /* + An event sent when the spending transaction of the request was + reorged out of the chain. + */ + Reorg reorg = 2; + } +} + +message BlockEpoch { + // The hash of the block. + bytes hash = 1; + + // The height of the block. + uint32 height = 2; +} diff --git a/proto/gen_protos_docker.sh b/proto/gen_protos_docker.sh index 6f598c9ef..78fc48fdb 100755 --- a/proto/gen_protos_docker.sh +++ b/proto/gen_protos_docker.sh @@ -13,5 +13,6 @@ docker run \ --rm \ --user $UID:$UID \ -e UID=$UID \ + -e SUBSERVER_PREFIX \ -v "$DIR/../:/build" \ lit-protobuf-builder diff --git a/proto/invoicesrpc/invoices.proto b/proto/invoicesrpc/invoices.proto new file mode 100644 index 000000000..12317d02c --- /dev/null +++ b/proto/invoicesrpc/invoices.proto @@ -0,0 +1,175 @@ +syntax = "proto3"; + +import "lightning.proto"; + +package invoicesrpc; + +option go_package = "github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"; + +// Invoices is a service that can be used to create, accept, settle and cancel +// invoices. +service Invoices { + /* + SubscribeSingleInvoice returns a uni-directional stream (server -> client) + to notify the client of state transitions of the specified invoice. + Initially the current invoice state is always sent out. + */ + rpc SubscribeSingleInvoice (SubscribeSingleInvoiceRequest) + returns (stream lnrpc.Invoice); + + /* + CancelInvoice cancels a currently open invoice. If the invoice is already + canceled, this call will succeed. If the invoice is already settled, it will + fail. + */ + rpc CancelInvoice (CancelInvoiceMsg) returns (CancelInvoiceResp); + + /* + AddHoldInvoice creates a hold invoice. It ties the invoice to the hash + supplied in the request. + */ + rpc AddHoldInvoice (AddHoldInvoiceRequest) returns (AddHoldInvoiceResp); + + /* + SettleInvoice settles an accepted invoice. If the invoice is already + settled, this call will succeed. + */ + rpc SettleInvoice (SettleInvoiceMsg) returns (SettleInvoiceResp); + + /* + LookupInvoiceV2 attempts to look up at invoice. An invoice can be refrenced + using either its payment hash, payment address, or set ID. + */ + rpc LookupInvoiceV2 (LookupInvoiceMsg) returns (lnrpc.Invoice); +} + +message CancelInvoiceMsg { + // Hash corresponding to the (hold) invoice to cancel. When using + // REST, this field must be encoded as base64. + bytes payment_hash = 1; +} +message CancelInvoiceResp { +} + +message AddHoldInvoiceRequest { + /* + An optional memo to attach along with the invoice. Used for record keeping + purposes for the invoice's creator, and will also be set in the description + field of the encoded payment request if the description_hash field is not + being used. + */ + string memo = 1; + + // The hash of the preimage + bytes hash = 2; + + /* + The value of this invoice in satoshis + + The fields value and value_msat are mutually exclusive. + */ + int64 value = 3; + + /* + The value of this invoice in millisatoshis + + The fields value and value_msat are mutually exclusive. + */ + int64 value_msat = 10; + + /* + Hash (SHA-256) of a description of the payment. Used if the description of + payment (memo) is too long to naturally fit within the description field + of an encoded payment request. + */ + bytes description_hash = 4; + + // Payment request expiry time in seconds. Default is 86400 (24 hours). + int64 expiry = 5; + + // Fallback on-chain address. + string fallback_addr = 6; + + // Delta to use for the time-lock of the CLTV extended to the final hop. + uint64 cltv_expiry = 7; + + /* + Route hints that can each be individually used to assist in reaching the + invoice's destination. + */ + repeated lnrpc.RouteHint route_hints = 8; + + // Whether this invoice should include routing hints for private channels. + bool private = 9; +} + +message AddHoldInvoiceResp { + /* + A bare-bones invoice for a payment within the Lightning Network. With the + details of the invoice, the sender has all the data necessary to send a + payment to the recipient. + */ + string payment_request = 1; + + /* + The "add" index of this invoice. Each newly created invoice will increment + this index making it monotonically increasing. Callers to the + SubscribeInvoices call can use this to instantly get notified of all added + invoices with an add_index greater than this one. + */ + uint64 add_index = 2; + + /* + The payment address of the generated invoice. This value should be used + in all payments for this invoice as we require it for end to end + security. + */ + bytes payment_addr = 3; +} + +message SettleInvoiceMsg { + // Externally discovered pre-image that should be used to settle the hold + // invoice. + bytes preimage = 1; +} + +message SettleInvoiceResp { +} + +message SubscribeSingleInvoiceRequest { + reserved 1; + + // Hash corresponding to the (hold) invoice to subscribe to. When using + // REST, this field must be encoded as base64url. + bytes r_hash = 2; +} + +enum LookupModifier { + // The default look up modifier, no look up behavior is changed. + DEFAULT = 0; + + /* + Indicates that when a look up is done based on a set_id, then only that set + of HTLCs related to that set ID should be returned. + */ + HTLC_SET_ONLY = 1; + + /* + Indicates that when a look up is done using a payment_addr, then no HTLCs + related to the payment_addr should be returned. This is useful when one + wants to be able to obtain the set of associated setIDs with a given + invoice, then look up the sub-invoices "projected" by that set ID. + */ + HTLC_SET_BLANK = 2; +} + +message LookupInvoiceMsg { + oneof invoice_ref { + // When using REST, this field must be encoded as base64. + bytes payment_hash = 1; + bytes payment_addr = 2; + bytes set_id = 3; + } + + LookupModifier lookup_modifier = 4; +} diff --git a/proto/lightning.proto b/proto/lightning.proto new file mode 100644 index 000000000..8a41a5a2e --- /dev/null +++ b/proto/lightning.proto @@ -0,0 +1,4957 @@ +syntax = "proto3"; + +package lnrpc; + +option go_package = "github.com/lightningnetwork/lnd/lnrpc"; + +/* + * Comments in this file will be directly parsed into the API + * Documentation as descriptions of the associated method, message, or field. + * These descriptions should go right above the definition of the object, and + * can be in either block or // comment format. + * + * An RPC method can be matched to an lncli command by placing a line in the + * beginning of the description in exactly the following format: + * lncli: `methodname` + * + * Failure to specify the exact name of the command will cause documentation + * generation to fail. + * + * More information on how exactly the gRPC documentation is generated from + * this proto file can be found here: + * https://github.com/lightninglabs/lightning-api + */ + +// Lightning is the main RPC server of the daemon. +service Lightning { + /* lncli: `walletbalance` + WalletBalance returns total unspent outputs(confirmed and unconfirmed), all + confirmed unspent outputs and all unconfirmed unspent outputs under control + of the wallet. + */ + rpc WalletBalance (WalletBalanceRequest) returns (WalletBalanceResponse); + + /* lncli: `channelbalance` + ChannelBalance returns a report on the total funds across all open channels, + categorized in local/remote, pending local/remote and unsettled local/remote + balances. + */ + rpc ChannelBalance (ChannelBalanceRequest) returns (ChannelBalanceResponse); + + /* lncli: `listchaintxns` + GetTransactions returns a list describing all the known transactions + relevant to the wallet. + */ + rpc GetTransactions (GetTransactionsRequest) returns (TransactionDetails); + + /* lncli: `estimatefee` + EstimateFee asks the chain backend to estimate the fee rate and total fees + for a transaction that pays to multiple specified outputs. + + When using REST, the `AddrToAmount` map type can be set by appending + `&AddrToAmount[
]=` to the URL. Unfortunately this + map type doesn't appear in the REST API documentation because of a bug in + the grpc-gateway library. + */ + rpc EstimateFee (EstimateFeeRequest) returns (EstimateFeeResponse); + + /* lncli: `sendcoins` + SendCoins executes a request to send coins to a particular address. Unlike + SendMany, this RPC call only allows creating a single output at a time. If + neither target_conf, or sat_per_vbyte are set, then the internal wallet will + consult its fee model to determine a fee for the default confirmation + target. + */ + rpc SendCoins (SendCoinsRequest) returns (SendCoinsResponse); + + /* lncli: `listunspent` + Deprecated, use walletrpc.ListUnspent instead. + + ListUnspent returns a list of all utxos spendable by the wallet with a + number of confirmations between the specified minimum and maximum. + */ + rpc ListUnspent (ListUnspentRequest) returns (ListUnspentResponse); + + /* + SubscribeTransactions creates a uni-directional stream from the server to + the client in which any newly discovered transactions relevant to the + wallet are sent over. + */ + rpc SubscribeTransactions (GetTransactionsRequest) + returns (stream Transaction); + + /* lncli: `sendmany` + SendMany handles a request for a transaction that creates multiple specified + outputs in parallel. If neither target_conf, or sat_per_vbyte are set, then + the internal wallet will consult its fee model to determine a fee for the + default confirmation target. + */ + rpc SendMany (SendManyRequest) returns (SendManyResponse); + + /* lncli: `newaddress` + NewAddress creates a new address under control of the local wallet. + */ + rpc NewAddress (NewAddressRequest) returns (NewAddressResponse); + + /* lncli: `signmessage` + SignMessage signs a message with this node's private key. The returned + signature string is `zbase32` encoded and pubkey recoverable, meaning that + only the message digest and signature are needed for verification. + */ + rpc SignMessage (SignMessageRequest) returns (SignMessageResponse); + + /* lncli: `verifymessage` + VerifyMessage verifies a signature over a message and recovers the signer's + public key. The signature is only deemed valid if the recovered public key + corresponds to a node key in the public Lightning network. The signature + must be zbase32 encoded and signed by an active node in the resident node's + channel database. In addition to returning the validity of the signature, + VerifyMessage also returns the recovered pubkey from the signature. + */ + rpc VerifyMessage (VerifyMessageRequest) returns (VerifyMessageResponse); + + /* lncli: `connect` + ConnectPeer attempts to establish a connection to a remote peer. This is at + the networking level, and is used for communication between nodes. This is + distinct from establishing a channel with a peer. + */ + rpc ConnectPeer (ConnectPeerRequest) returns (ConnectPeerResponse); + + /* lncli: `disconnect` + DisconnectPeer attempts to disconnect one peer from another identified by a + given pubKey. In the case that we currently have a pending or active channel + with the target peer, then this action will be not be allowed. + */ + rpc DisconnectPeer (DisconnectPeerRequest) returns (DisconnectPeerResponse); + + /* lncli: `listpeers` + ListPeers returns a verbose listing of all currently active peers. + */ + rpc ListPeers (ListPeersRequest) returns (ListPeersResponse); + + /* + SubscribePeerEvents creates a uni-directional stream from the server to + the client in which any events relevant to the state of peers are sent + over. Events include peers going online and offline. + */ + rpc SubscribePeerEvents (PeerEventSubscription) returns (stream PeerEvent); + + /* lncli: `getinfo` + GetInfo returns general information concerning the lightning node including + it's identity pubkey, alias, the chains it is connected to, and information + concerning the number of open+pending channels. + */ + rpc GetInfo (GetInfoRequest) returns (GetInfoResponse); + + /** lncli: `getrecoveryinfo` + GetRecoveryInfo returns information concerning the recovery mode including + whether it's in a recovery mode, whether the recovery is finished, and the + progress made so far. + */ + rpc GetRecoveryInfo (GetRecoveryInfoRequest) + returns (GetRecoveryInfoResponse); + + // TODO(roasbeef): merge with below with bool? + /* lncli: `pendingchannels` + PendingChannels returns a list of all the channels that are currently + considered "pending". A channel is pending if it has finished the funding + workflow and is waiting for confirmations for the funding txn, or is in the + process of closure, either initiated cooperatively or non-cooperatively. + */ + rpc PendingChannels (PendingChannelsRequest) + returns (PendingChannelsResponse); + + /* lncli: `listchannels` + ListChannels returns a description of all the open channels that this node + is a participant in. + */ + rpc ListChannels (ListChannelsRequest) returns (ListChannelsResponse); + + /* + SubscribeChannelEvents creates a uni-directional stream from the server to + the client in which any updates relevant to the state of the channels are + sent over. Events include new active channels, inactive channels, and closed + channels. + */ + rpc SubscribeChannelEvents (ChannelEventSubscription) + returns (stream ChannelEventUpdate); + + /* lncli: `closedchannels` + ClosedChannels returns a description of all the closed channels that + this node was a participant in. + */ + rpc ClosedChannels (ClosedChannelsRequest) returns (ClosedChannelsResponse); + + /* + OpenChannelSync is a synchronous version of the OpenChannel RPC call. This + call is meant to be consumed by clients to the REST proxy. As with all + other sync calls, all byte slices are intended to be populated as hex + encoded strings. + */ + rpc OpenChannelSync (OpenChannelRequest) returns (ChannelPoint); + + /* lncli: `openchannel` + OpenChannel attempts to open a singly funded channel specified in the + request to a remote peer. Users are able to specify a target number of + blocks that the funding transaction should be confirmed in, or a manual fee + rate to us for the funding transaction. If neither are specified, then a + lax block confirmation target is used. Each OpenStatusUpdate will return + the pending channel ID of the in-progress channel. Depending on the + arguments specified in the OpenChannelRequest, this pending channel ID can + then be used to manually progress the channel funding flow. + */ + rpc OpenChannel (OpenChannelRequest) returns (stream OpenStatusUpdate); + + /* lncli: `batchopenchannel` + BatchOpenChannel attempts to open multiple single-funded channels in a + single transaction in an atomic way. This means either all channel open + requests succeed at once or all attempts are aborted if any of them fail. + This is the safer variant of using PSBTs to manually fund a batch of + channels through the OpenChannel RPC. + */ + rpc BatchOpenChannel (BatchOpenChannelRequest) + returns (BatchOpenChannelResponse); + + /* + FundingStateStep is an advanced funding related call that allows the caller + to either execute some preparatory steps for a funding workflow, or + manually progress a funding workflow. The primary way a funding flow is + identified is via its pending channel ID. As an example, this method can be + used to specify that we're expecting a funding flow for a particular + pending channel ID, for which we need to use specific parameters. + Alternatively, this can be used to interactively drive PSBT signing for + funding for partially complete funding transactions. + */ + rpc FundingStateStep (FundingTransitionMsg) returns (FundingStateStepResp); + + /* + ChannelAcceptor dispatches a bi-directional streaming RPC in which + OpenChannel requests are sent to the client and the client responds with + a boolean that tells LND whether or not to accept the channel. This allows + node operators to specify their own criteria for accepting inbound channels + through a single persistent connection. + */ + rpc ChannelAcceptor (stream ChannelAcceptResponse) + returns (stream ChannelAcceptRequest); + + /* lncli: `closechannel` + CloseChannel attempts to close an active channel identified by its channel + outpoint (ChannelPoint). The actions of this method can additionally be + augmented to attempt a force close after a timeout period in the case of an + inactive peer. If a non-force close (cooperative closure) is requested, + then the user can specify either a target number of blocks until the + closure transaction is confirmed, or a manual fee rate. If neither are + specified, then a default lax, block confirmation target is used. + */ + rpc CloseChannel (CloseChannelRequest) returns (stream CloseStatusUpdate); + + /* lncli: `abandonchannel` + AbandonChannel removes all channel state from the database except for a + close summary. This method can be used to get rid of permanently unusable + channels due to bugs fixed in newer versions of lnd. This method can also be + used to remove externally funded channels where the funding transaction was + never broadcast. Only available for non-externally funded channels in dev + build. + */ + rpc AbandonChannel (AbandonChannelRequest) returns (AbandonChannelResponse); + + /* lncli: `sendpayment` + Deprecated, use routerrpc.SendPaymentV2. SendPayment dispatches a + bi-directional streaming RPC for sending payments through the Lightning + Network. A single RPC invocation creates a persistent bi-directional + stream allowing clients to rapidly send payments through the Lightning + Network with a single persistent connection. + */ + rpc SendPayment (stream SendRequest) returns (stream SendResponse) { + option deprecated = true; + } + + /* + SendPaymentSync is the synchronous non-streaming version of SendPayment. + This RPC is intended to be consumed by clients of the REST proxy. + Additionally, this RPC expects the destination's public key and the payment + hash (if any) to be encoded as hex strings. + */ + rpc SendPaymentSync (SendRequest) returns (SendResponse); + + /* lncli: `sendtoroute` + Deprecated, use routerrpc.SendToRouteV2. SendToRoute is a bi-directional + streaming RPC for sending payment through the Lightning Network. This + method differs from SendPayment in that it allows users to specify a full + route manually. This can be used for things like rebalancing, and atomic + swaps. + */ + rpc SendToRoute (stream SendToRouteRequest) returns (stream SendResponse) { + option deprecated = true; + } + + /* + SendToRouteSync is a synchronous version of SendToRoute. It Will block + until the payment either fails or succeeds. + */ + rpc SendToRouteSync (SendToRouteRequest) returns (SendResponse); + + /* lncli: `addinvoice` + AddInvoice attempts to add a new invoice to the invoice database. Any + duplicated invoices are rejected, therefore all invoices *must* have a + unique payment preimage. + */ + rpc AddInvoice (Invoice) returns (AddInvoiceResponse); + + /* lncli: `listinvoices` + ListInvoices returns a list of all the invoices currently stored within the + database. Any active debug invoices are ignored. It has full support for + paginated responses, allowing users to query for specific invoices through + their add_index. This can be done by using either the first_index_offset or + last_index_offset fields included in the response as the index_offset of the + next request. By default, the first 100 invoices created will be returned. + Backwards pagination is also supported through the Reversed flag. + */ + rpc ListInvoices (ListInvoiceRequest) returns (ListInvoiceResponse); + + /* lncli: `lookupinvoice` + LookupInvoice attempts to look up an invoice according to its payment hash. + The passed payment hash *must* be exactly 32 bytes, if not, an error is + returned. + */ + rpc LookupInvoice (PaymentHash) returns (Invoice); + + /* + SubscribeInvoices returns a uni-directional stream (server -> client) for + notifying the client of newly added/settled invoices. The caller can + optionally specify the add_index and/or the settle_index. If the add_index + is specified, then we'll first start by sending add invoice events for all + invoices with an add_index greater than the specified value. If the + settle_index is specified, the next, we'll send out all settle events for + invoices with a settle_index greater than the specified value. One or both + of these fields can be set. If no fields are set, then we'll only send out + the latest add/settle events. + */ + rpc SubscribeInvoices (InvoiceSubscription) returns (stream Invoice); + + /* lncli: `decodepayreq` + DecodePayReq takes an encoded payment request string and attempts to decode + it, returning a full description of the conditions encoded within the + payment request. + */ + rpc DecodePayReq (PayReqString) returns (PayReq); + + /* lncli: `listpayments` + ListPayments returns a list of all outgoing payments. + */ + rpc ListPayments (ListPaymentsRequest) returns (ListPaymentsResponse); + + /* + DeletePayment deletes an outgoing payment from DB. Note that it will not + attempt to delete an In-Flight payment, since that would be unsafe. + */ + rpc DeletePayment (DeletePaymentRequest) returns (DeletePaymentResponse); + + /* + DeleteAllPayments deletes all outgoing payments from DB. Note that it will + not attempt to delete In-Flight payments, since that would be unsafe. + */ + rpc DeleteAllPayments (DeleteAllPaymentsRequest) + returns (DeleteAllPaymentsResponse); + + /* lncli: `describegraph` + DescribeGraph returns a description of the latest graph state from the + point of view of the node. The graph information is partitioned into two + components: all the nodes/vertexes, and all the edges that connect the + vertexes themselves. As this is a directed graph, the edges also contain + the node directional specific routing policy which includes: the time lock + delta, fee information, etc. + */ + rpc DescribeGraph (ChannelGraphRequest) returns (ChannelGraph); + + /* lncli: `getnodemetrics` + GetNodeMetrics returns node metrics calculated from the graph. Currently + the only supported metric is betweenness centrality of individual nodes. + */ + rpc GetNodeMetrics (NodeMetricsRequest) returns (NodeMetricsResponse); + + /* lncli: `getchaninfo` + GetChanInfo returns the latest authenticated network announcement for the + given channel identified by its channel ID: an 8-byte integer which + uniquely identifies the location of transaction's funding output within the + blockchain. + */ + rpc GetChanInfo (ChanInfoRequest) returns (ChannelEdge); + + /* lncli: `getnodeinfo` + GetNodeInfo returns the latest advertised, aggregated, and authenticated + channel information for the specified node identified by its public key. + */ + rpc GetNodeInfo (NodeInfoRequest) returns (NodeInfo); + + /* lncli: `queryroutes` + QueryRoutes attempts to query the daemon's Channel Router for a possible + route to a target destination capable of carrying a specific amount of + satoshis. The returned route contains the full details required to craft and + send an HTLC, also including the necessary information that should be + present within the Sphinx packet encapsulated within the HTLC. + + When using REST, the `dest_custom_records` map type can be set by appending + `&dest_custom_records[]=` + to the URL. Unfortunately this map type doesn't appear in the REST API + documentation because of a bug in the grpc-gateway library. + */ + rpc QueryRoutes (QueryRoutesRequest) returns (QueryRoutesResponse); + + /* lncli: `getnetworkinfo` + GetNetworkInfo returns some basic stats about the known channel graph from + the point of view of the node. + */ + rpc GetNetworkInfo (NetworkInfoRequest) returns (NetworkInfo); + + /* lncli: `stop` + StopDaemon will send a shutdown request to the interrupt handler, triggering + a graceful shutdown of the daemon. + */ + rpc StopDaemon (StopRequest) returns (StopResponse); + + /* + SubscribeChannelGraph launches a streaming RPC that allows the caller to + receive notifications upon any changes to the channel graph topology from + the point of view of the responding node. Events notified include: new + nodes coming online, nodes updating their authenticated attributes, new + channels being advertised, updates in the routing policy for a directional + channel edge, and when channels are closed on-chain. + */ + rpc SubscribeChannelGraph (GraphTopologySubscription) + returns (stream GraphTopologyUpdate); + + /* lncli: `debuglevel` + DebugLevel allows a caller to programmatically set the logging verbosity of + lnd. The logging can be targeted according to a coarse daemon-wide logging + level, or in a granular fashion to specify the logging for a target + sub-system. + */ + rpc DebugLevel (DebugLevelRequest) returns (DebugLevelResponse); + + /* lncli: `feereport` + FeeReport allows the caller to obtain a report detailing the current fee + schedule enforced by the node globally for each channel. + */ + rpc FeeReport (FeeReportRequest) returns (FeeReportResponse); + + /* lncli: `updatechanpolicy` + UpdateChannelPolicy allows the caller to update the fee schedule and + channel policies for all channels globally, or a particular channel. + */ + rpc UpdateChannelPolicy (PolicyUpdateRequest) + returns (PolicyUpdateResponse); + + /* lncli: `fwdinghistory` + ForwardingHistory allows the caller to query the htlcswitch for a record of + all HTLCs forwarded within the target time range, and integer offset + within that time range, for a maximum number of events. If no maximum number + of events is specified, up to 100 events will be returned. If no time-range + is specified, then events will be returned in the order that they occured. + + A list of forwarding events are returned. The size of each forwarding event + is 40 bytes, and the max message size able to be returned in gRPC is 4 MiB. + As a result each message can only contain 50k entries. Each response has + the index offset of the last entry. The index offset can be provided to the + request to allow the caller to skip a series of records. + */ + rpc ForwardingHistory (ForwardingHistoryRequest) + returns (ForwardingHistoryResponse); + + /* lncli: `exportchanbackup` + ExportChannelBackup attempts to return an encrypted static channel backup + for the target channel identified by it channel point. The backup is + encrypted with a key generated from the aezeed seed of the user. The + returned backup can either be restored using the RestoreChannelBackup + method once lnd is running, or via the InitWallet and UnlockWallet methods + from the WalletUnlocker service. + */ + rpc ExportChannelBackup (ExportChannelBackupRequest) + returns (ChannelBackup); + + /* + ExportAllChannelBackups returns static channel backups for all existing + channels known to lnd. A set of regular singular static channel backups for + each channel are returned. Additionally, a multi-channel backup is returned + as well, which contains a single encrypted blob containing the backups of + each channel. + */ + rpc ExportAllChannelBackups (ChanBackupExportRequest) + returns (ChanBackupSnapshot); + + /* + VerifyChanBackup allows a caller to verify the integrity of a channel backup + snapshot. This method will accept either a packed Single or a packed Multi. + Specifying both will result in an error. + */ + rpc VerifyChanBackup (ChanBackupSnapshot) + returns (VerifyChanBackupResponse); + + /* lncli: `restorechanbackup` + RestoreChannelBackups accepts a set of singular channel backups, or a + single encrypted multi-chan backup and attempts to recover any funds + remaining within the channel. If we are able to unpack the backup, then the + new channel will be shown under listchannels, as well as pending channels. + */ + rpc RestoreChannelBackups (RestoreChanBackupRequest) + returns (RestoreBackupResponse); + + /* + SubscribeChannelBackups allows a client to sub-subscribe to the most up to + date information concerning the state of all channel backups. Each time a + new channel is added, we return the new set of channels, along with a + multi-chan backup containing the backup info for all channels. Each time a + channel is closed, we send a new update, which contains new new chan back + ups, but the updated set of encrypted multi-chan backups with the closed + channel(s) removed. + */ + rpc SubscribeChannelBackups (ChannelBackupSubscription) + returns (stream ChanBackupSnapshot); + + /* lncli: `bakemacaroon` + BakeMacaroon allows the creation of a new macaroon with custom read and + write permissions. No first-party caveats are added since this can be done + offline. + */ + rpc BakeMacaroon (BakeMacaroonRequest) returns (BakeMacaroonResponse); + + /* lncli: `listmacaroonids` + ListMacaroonIDs returns all root key IDs that are in use. + */ + rpc ListMacaroonIDs (ListMacaroonIDsRequest) + returns (ListMacaroonIDsResponse); + + /* lncli: `deletemacaroonid` + DeleteMacaroonID deletes the specified macaroon ID and invalidates all + macaroons derived from that ID. + */ + rpc DeleteMacaroonID (DeleteMacaroonIDRequest) + returns (DeleteMacaroonIDResponse); + + /* lncli: `listpermissions` + ListPermissions lists all RPC method URIs and their required macaroon + permissions to access them. + */ + rpc ListPermissions (ListPermissionsRequest) + returns (ListPermissionsResponse); + + /* + CheckMacaroonPermissions checks whether a request follows the constraints + imposed on the macaroon and that the macaroon is authorized to follow the + provided permissions. + */ + rpc CheckMacaroonPermissions (CheckMacPermRequest) + returns (CheckMacPermResponse); + + /* + RegisterRPCMiddleware adds a new gRPC middleware to the interceptor chain. A + gRPC middleware is software component external to lnd that aims to add + additional business logic to lnd by observing/intercepting/validating + incoming gRPC client requests and (if needed) replacing/overwriting outgoing + messages before they're sent to the client. When registering the middleware + must identify itself and indicate what custom macaroon caveats it wants to + be responsible for. Only requests that contain a macaroon with that specific + custom caveat are then sent to the middleware for inspection. The other + option is to register for the read-only mode in which all requests/responses + are forwarded for interception to the middleware but the middleware is not + allowed to modify any responses. As a security measure, _no_ middleware can + modify responses for requests made with _unencumbered_ macaroons! + */ + rpc RegisterRPCMiddleware (stream RPCMiddlewareResponse) + returns (stream RPCMiddlewareRequest); + + /* lncli: `sendcustom` + SendCustomMessage sends a custom peer message. + */ + rpc SendCustomMessage (SendCustomMessageRequest) + returns (SendCustomMessageResponse); + + /* lncli: `subscribecustom` + SubscribeCustomMessages subscribes to a stream of incoming custom peer + messages. + + To include messages with type outside of the custom range (>= 32768) lnd + needs to be compiled with the `dev` build tag, and the message type to + override should be specified in lnd's experimental protocol configuration. + */ + rpc SubscribeCustomMessages (SubscribeCustomMessagesRequest) + returns (stream CustomMessage); + + /* lncli: `listaliases` + ListAliases returns the set of all aliases that have ever existed with + their confirmed SCID (if it exists) and/or the base SCID (in the case of + zero conf). + */ + rpc ListAliases (ListAliasesRequest) returns (ListAliasesResponse); + + /* + LookupHtlcResolution retrieves a final htlc resolution from the database. + If the htlc has no final resolution yet, a NotFound grpc status code is + returned. + */ + rpc LookupHtlcResolution (LookupHtlcResolutionRequest) + returns (LookupHtlcResolutionResponse); +} + +message LookupHtlcResolutionRequest { + uint64 chan_id = 1; + + uint64 htlc_index = 2; +} + +message LookupHtlcResolutionResponse { + // Settled is true is the htlc was settled. If false, the htlc was failed. + bool settled = 1; + + // Offchain indicates whether the htlc was resolved off-chain or on-chain. + bool offchain = 2; +} + +message SubscribeCustomMessagesRequest { +} + +message CustomMessage { + // Peer from which the message originates + bytes peer = 1; + + // Message type. This value will be in the custom range (>= 32768). + uint32 type = 2; + + // Raw message data + bytes data = 3; +} + +message SendCustomMessageRequest { + // Peer to send the message to + bytes peer = 1; + + // Message type. This value needs to be in the custom range (>= 32768). + // To send a type < custom range, lnd needs to be compiled with the `dev` + // build tag, and the message type to override should be specified in lnd's + // experimental protocol configuration. + uint32 type = 2; + + // Raw message data. + bytes data = 3; +} + +message SendCustomMessageResponse { +} + +message Utxo { + // The type of address + AddressType address_type = 1; + + // The address + string address = 2; + + // The value of the unspent coin in satoshis + int64 amount_sat = 3; + + // The pkscript in hex + string pk_script = 4; + + // The outpoint in format txid:n + OutPoint outpoint = 5; + + // The number of confirmations for the Utxo + int64 confirmations = 6; +} + +enum OutputScriptType { + SCRIPT_TYPE_PUBKEY_HASH = 0; + SCRIPT_TYPE_SCRIPT_HASH = 1; + SCRIPT_TYPE_WITNESS_V0_PUBKEY_HASH = 2; + SCRIPT_TYPE_WITNESS_V0_SCRIPT_HASH = 3; + SCRIPT_TYPE_PUBKEY = 4; + SCRIPT_TYPE_MULTISIG = 5; + SCRIPT_TYPE_NULLDATA = 6; + SCRIPT_TYPE_NON_STANDARD = 7; + SCRIPT_TYPE_WITNESS_UNKNOWN = 8; + SCRIPT_TYPE_WITNESS_V1_TAPROOT = 9; +} + +message OutputDetail { + // The type of the output + OutputScriptType output_type = 1; + + // The address + string address = 2; + + // The pkscript in hex + string pk_script = 3; + + // The output index used in the raw transaction + int64 output_index = 4; + + // The value of the output coin in satoshis + int64 amount = 5; + + // Denotes if the output is controlled by the internal wallet + bool is_our_address = 6; +} + +message Transaction { + // The transaction hash + string tx_hash = 1; + + // The transaction amount, denominated in satoshis + int64 amount = 2; + + // The number of confirmations + int32 num_confirmations = 3; + + // The hash of the block this transaction was included in + string block_hash = 4; + + // The height of the block this transaction was included in + int32 block_height = 5; + + // Timestamp of this transaction + int64 time_stamp = 6; + + // Fees paid for this transaction + int64 total_fees = 7; + + // Addresses that received funds for this transaction. Deprecated as it is + // now incorporated in the output_details field. + repeated string dest_addresses = 8 [deprecated = true]; + + // Outputs that received funds for this transaction + repeated OutputDetail output_details = 11; + + // The raw transaction hex. + string raw_tx_hex = 9; + + // A label that was optionally set on transaction broadcast. + string label = 10; + + // PreviousOutpoints/Inputs of this transaction. + repeated PreviousOutPoint previous_outpoints = 12; +} + +message GetTransactionsRequest { + /* + The height from which to list transactions, inclusive. If this value is + greater than end_height, transactions will be read in reverse. + */ + int32 start_height = 1; + + /* + The height until which to list transactions, inclusive. To include + unconfirmed transactions, this value should be set to -1, which will + return transactions from start_height until the current chain tip and + unconfirmed transactions. If no end_height is provided, the call will + default to this option. + */ + int32 end_height = 2; + + // An optional filter to only include transactions relevant to an account. + string account = 3; +} + +message TransactionDetails { + // The list of transactions relevant to the wallet. + repeated Transaction transactions = 1; +} + +message FeeLimit { + oneof limit { + /* + The fee limit expressed as a fixed amount of satoshis. + + The fields fixed and fixed_msat are mutually exclusive. + */ + int64 fixed = 1; + + /* + The fee limit expressed as a fixed amount of millisatoshis. + + The fields fixed and fixed_msat are mutually exclusive. + */ + int64 fixed_msat = 3; + + // The fee limit expressed as a percentage of the payment amount. + int64 percent = 2; + } +} + +message SendRequest { + /* + The identity pubkey of the payment recipient. When using REST, this field + must be encoded as base64. + */ + bytes dest = 1; + + /* + The hex-encoded identity pubkey of the payment recipient. Deprecated now + that the REST gateway supports base64 encoding of bytes fields. + */ + string dest_string = 2 [deprecated = true]; + + /* + The amount to send expressed in satoshis. + + The fields amt and amt_msat are mutually exclusive. + */ + int64 amt = 3; + + /* + The amount to send expressed in millisatoshis. + + The fields amt and amt_msat are mutually exclusive. + */ + int64 amt_msat = 12; + + /* + The hash to use within the payment's HTLC. When using REST, this field + must be encoded as base64. + */ + bytes payment_hash = 4; + + /* + The hex-encoded hash to use within the payment's HTLC. Deprecated now + that the REST gateway supports base64 encoding of bytes fields. + */ + string payment_hash_string = 5 [deprecated = true]; + + /* + A bare-bones invoice for a payment within the Lightning Network. With the + details of the invoice, the sender has all the data necessary to send a + payment to the recipient. + */ + string payment_request = 6; + + /* + The CLTV delta from the current height that should be used to set the + timelock for the final hop. + */ + int32 final_cltv_delta = 7; + + /* + The maximum number of satoshis that will be paid as a fee of the payment. + This value can be represented either as a percentage of the amount being + sent, or as a fixed amount of the maximum fee the user is willing the pay to + send the payment. If not specified, lnd will use a default value of 100% + fees for small amounts (<=1k sat) or 5% fees for larger amounts. + */ + FeeLimit fee_limit = 8; + + /* + The channel id of the channel that must be taken to the first hop. If zero, + any channel may be used. + */ + uint64 outgoing_chan_id = 9 [jstype = JS_STRING]; + + /* + The pubkey of the last hop of the route. If empty, any hop may be used. + */ + bytes last_hop_pubkey = 13; + + /* + An optional maximum total time lock for the route. This should not exceed + lnd's `--max-cltv-expiry` setting. If zero, then the value of + `--max-cltv-expiry` is enforced. + */ + uint32 cltv_limit = 10; + + /* + An optional field that can be used to pass an arbitrary set of TLV records + to a peer which understands the new records. This can be used to pass + application specific data during the payment attempt. Record types are + required to be in the custom range >= 65536. When using REST, the values + must be encoded as base64. + */ + map dest_custom_records = 11; + + // If set, circular payments to self are permitted. + bool allow_self_payment = 14; + + /* + Features assumed to be supported by the final node. All transitive feature + dependencies must also be set properly. For a given feature bit pair, either + optional or remote may be set, but not both. If this field is nil or empty, + the router will try to load destination features from the graph as a + fallback. + */ + repeated FeatureBit dest_features = 15; + + /* + The payment address of the generated invoice. + */ + bytes payment_addr = 16; +} + +message SendResponse { + string payment_error = 1; + bytes payment_preimage = 2; + Route payment_route = 3; + bytes payment_hash = 4; +} + +message SendToRouteRequest { + /* + The payment hash to use for the HTLC. When using REST, this field must be + encoded as base64. + */ + bytes payment_hash = 1; + + /* + An optional hex-encoded payment hash to be used for the HTLC. Deprecated now + that the REST gateway supports base64 encoding of bytes fields. + */ + string payment_hash_string = 2 [deprecated = true]; + + reserved 3; + + // Route that should be used to attempt to complete the payment. + Route route = 4; +} + +message ChannelAcceptRequest { + // The pubkey of the node that wishes to open an inbound channel. + bytes node_pubkey = 1; + + // The hash of the genesis block that the proposed channel resides in. + bytes chain_hash = 2; + + // The pending channel id. + bytes pending_chan_id = 3; + + // The funding amount in satoshis that initiator wishes to use in the + // channel. + uint64 funding_amt = 4; + + // The push amount of the proposed channel in millisatoshis. + uint64 push_amt = 5; + + // The dust limit of the initiator's commitment tx. + uint64 dust_limit = 6; + + // The maximum amount of coins in millisatoshis that can be pending in this + // channel. + uint64 max_value_in_flight = 7; + + // The minimum amount of satoshis the initiator requires us to have at all + // times. + uint64 channel_reserve = 8; + + // The smallest HTLC in millisatoshis that the initiator will accept. + uint64 min_htlc = 9; + + // The initial fee rate that the initiator suggests for both commitment + // transactions. + uint64 fee_per_kw = 10; + + /* + The number of blocks to use for the relative time lock in the pay-to-self + output of both commitment transactions. + */ + uint32 csv_delay = 11; + + // The total number of incoming HTLC's that the initiator will accept. + uint32 max_accepted_htlcs = 12; + + // A bit-field which the initiator uses to specify proposed channel + // behavior. + uint32 channel_flags = 13; + + // The commitment type the initiator wishes to use for the proposed channel. + CommitmentType commitment_type = 14; + + // Whether the initiator wants to open a zero-conf channel via the channel + // type. + bool wants_zero_conf = 15; + + // Whether the initiator wants to use the scid-alias channel type. This is + // separate from the feature bit. + bool wants_scid_alias = 16; +} + +message ChannelAcceptResponse { + // Whether or not the client accepts the channel. + bool accept = 1; + + // The pending channel id to which this response applies. + bytes pending_chan_id = 2; + + /* + An optional error to send the initiating party to indicate why the channel + was rejected. This field *should not* contain sensitive information, it will + be sent to the initiating party. This field should only be set if accept is + false, the channel will be rejected if an error is set with accept=true + because the meaning of this response is ambiguous. Limited to 500 + characters. + */ + string error = 3; + + /* + The upfront shutdown address to use if the initiating peer supports option + upfront shutdown script (see ListPeers for the features supported). Note + that the channel open will fail if this value is set for a peer that does + not support this feature bit. + */ + string upfront_shutdown = 4; + + /* + The csv delay (in blocks) that we require for the remote party. + */ + uint32 csv_delay = 5; + + /* + The reserve amount in satoshis that we require the remote peer to adhere to. + We require that the remote peer always have some reserve amount allocated to + them so that there is always a disincentive to broadcast old state (if they + hold 0 sats on their side of the channel, there is nothing to lose). + */ + uint64 reserve_sat = 6; + + /* + The maximum amount of funds in millisatoshis that we allow the remote peer + to have in outstanding htlcs. + */ + uint64 in_flight_max_msat = 7; + + /* + The maximum number of htlcs that the remote peer can offer us. + */ + uint32 max_htlc_count = 8; + + /* + The minimum value in millisatoshis for incoming htlcs on the channel. + */ + uint64 min_htlc_in = 9; + + /* + The number of confirmations we require before we consider the channel open. + */ + uint32 min_accept_depth = 10; + + /* + Whether the responder wants this to be a zero-conf channel. This will fail + if either side does not have the scid-alias feature bit set. The minimum + depth field must be zero if this is true. + */ + bool zero_conf = 11; +} + +message ChannelPoint { + oneof funding_txid { + /* + Txid of the funding transaction. When using REST, this field must be + encoded as base64. + */ + bytes funding_txid_bytes = 1; + + /* + Hex-encoded string representing the byte-reversed hash of the funding + transaction. + */ + string funding_txid_str = 2; + } + + // The index of the output of the funding transaction + uint32 output_index = 3; +} + +message OutPoint { + // Raw bytes representing the transaction id. + bytes txid_bytes = 1; + + // Reversed, hex-encoded string representing the transaction id. + string txid_str = 2; + + // The index of the output on the transaction. + uint32 output_index = 3; +} + +message PreviousOutPoint { + // The outpoint in format txid:n. + string outpoint = 1; + + // Denotes if the outpoint is controlled by the internal wallet. + // The flag will only detect p2wkh, np2wkh and p2tr inputs as its own. + bool is_our_output = 2; +} + +message LightningAddress { + // The identity pubkey of the Lightning node. + string pubkey = 1; + + // The network location of the lightning node, e.g. `69.69.69.69:1337` or + // `localhost:10011`. + string host = 2; +} + +message EstimateFeeRequest { + // The map from addresses to amounts for the transaction. + map AddrToAmount = 1; + + // The target number of blocks that this transaction should be confirmed + // by. + int32 target_conf = 2; + + // The minimum number of confirmations each one of your outputs used for + // the transaction must satisfy. + int32 min_confs = 3; + + // Whether unconfirmed outputs should be used as inputs for the transaction. + bool spend_unconfirmed = 4; +} + +message EstimateFeeResponse { + // The total fee in satoshis. + int64 fee_sat = 1; + + // Deprecated, use sat_per_vbyte. + // The fee rate in satoshi/vbyte. + int64 feerate_sat_per_byte = 2 [deprecated = true]; + + // The fee rate in satoshi/vbyte. + uint64 sat_per_vbyte = 3; +} + +message SendManyRequest { + // The map from addresses to amounts + map AddrToAmount = 1; + + // The target number of blocks that this transaction should be confirmed + // by. + int32 target_conf = 3; + + // A manual fee rate set in sat/vbyte that should be used when crafting the + // transaction. + uint64 sat_per_vbyte = 4; + + // Deprecated, use sat_per_vbyte. + // A manual fee rate set in sat/vbyte that should be used when crafting the + // transaction. + int64 sat_per_byte = 5 [deprecated = true]; + + // An optional label for the transaction, limited to 500 characters. + string label = 6; + + // The minimum number of confirmations each one of your outputs used for + // the transaction must satisfy. + int32 min_confs = 7; + + // Whether unconfirmed outputs should be used as inputs for the transaction. + bool spend_unconfirmed = 8; +} +message SendManyResponse { + // The id of the transaction + string txid = 1; +} + +message SendCoinsRequest { + // The address to send coins to + string addr = 1; + + // The amount in satoshis to send + int64 amount = 2; + + // The target number of blocks that this transaction should be confirmed + // by. + int32 target_conf = 3; + + // A manual fee rate set in sat/vbyte that should be used when crafting the + // transaction. + uint64 sat_per_vbyte = 4; + + // Deprecated, use sat_per_vbyte. + // A manual fee rate set in sat/vbyte that should be used when crafting the + // transaction. + int64 sat_per_byte = 5 [deprecated = true]; + + /* + If set, then the amount field will be ignored, and lnd will attempt to + send all the coins under control of the internal wallet to the specified + address. + */ + bool send_all = 6; + + // An optional label for the transaction, limited to 500 characters. + string label = 7; + + // The minimum number of confirmations each one of your outputs used for + // the transaction must satisfy. + int32 min_confs = 8; + + // Whether unconfirmed outputs should be used as inputs for the transaction. + bool spend_unconfirmed = 9; +} +message SendCoinsResponse { + // The transaction ID of the transaction + string txid = 1; +} + +message ListUnspentRequest { + // The minimum number of confirmations to be included. + int32 min_confs = 1; + + // The maximum number of confirmations to be included. + int32 max_confs = 2; + + // An optional filter to only include outputs belonging to an account. + string account = 3; +} +message ListUnspentResponse { + // A list of utxos + repeated Utxo utxos = 1; +} + +/* +`AddressType` has to be one of: + +- `p2wkh`: Pay to witness key hash (`WITNESS_PUBKEY_HASH` = 0) +- `np2wkh`: Pay to nested witness key hash (`NESTED_PUBKEY_HASH` = 1) +- `p2tr`: Pay to taproot pubkey (`TAPROOT_PUBKEY` = 4) +*/ +enum AddressType { + WITNESS_PUBKEY_HASH = 0; + NESTED_PUBKEY_HASH = 1; + UNUSED_WITNESS_PUBKEY_HASH = 2; + UNUSED_NESTED_PUBKEY_HASH = 3; + TAPROOT_PUBKEY = 4; + UNUSED_TAPROOT_PUBKEY = 5; +} + +message NewAddressRequest { + // The type of address to generate. + AddressType type = 1; + + /* + The name of the account to generate a new address for. If empty, the + default wallet account is used. + */ + string account = 2; +} +message NewAddressResponse { + // The newly generated wallet address + string address = 1; +} + +message SignMessageRequest { + /* + The message to be signed. When using REST, this field must be encoded as + base64. + */ + bytes msg = 1; + + /* + Instead of the default double-SHA256 hashing of the message before signing, + only use one round of hashing instead. + */ + bool single_hash = 2; +} +message SignMessageResponse { + // The signature for the given message + string signature = 1; +} + +message VerifyMessageRequest { + /* + The message over which the signature is to be verified. When using REST, + this field must be encoded as base64. + */ + bytes msg = 1; + + // The signature to be verified over the given message + string signature = 2; +} +message VerifyMessageResponse { + // Whether the signature was valid over the given message + bool valid = 1; + + // The pubkey recovered from the signature + string pubkey = 2; +} + +message ConnectPeerRequest { + /* + Lightning address of the peer to connect to. + */ + LightningAddress addr = 1; + + /* + If set, the daemon will attempt to persistently connect to the target + peer. Otherwise, the call will be synchronous. + */ + bool perm = 2; + + /* + The connection timeout value (in seconds) for this request. It won't affect + other requests. + */ + uint64 timeout = 3; +} +message ConnectPeerResponse { +} + +message DisconnectPeerRequest { + // The pubkey of the node to disconnect from + string pub_key = 1; +} +message DisconnectPeerResponse { +} + +message HTLC { + bool incoming = 1; + int64 amount = 2; + bytes hash_lock = 3; + uint32 expiration_height = 4; + + // Index identifying the htlc on the channel. + uint64 htlc_index = 5; + + // If this HTLC is involved in a forwarding operation, this field indicates + // the forwarding channel. For an outgoing htlc, it is the incoming channel. + // For an incoming htlc, it is the outgoing channel. When the htlc + // originates from this node or this node is the final destination, + // forwarding_channel will be zero. The forwarding channel will also be zero + // for htlcs that need to be forwarded but don't have a forwarding decision + // persisted yet. + uint64 forwarding_channel = 6; + + // Index identifying the htlc on the forwarding channel. + uint64 forwarding_htlc_index = 7; +} + +enum CommitmentType { + /* + Returned when the commitment type isn't known or unavailable. + */ + UNKNOWN_COMMITMENT_TYPE = 0; + + /* + A channel using the legacy commitment format having tweaked to_remote + keys. + */ + LEGACY = 1; + + /* + A channel that uses the modern commitment format where the key in the + output of the remote party does not change each state. This makes back + up and recovery easier as when the channel is closed, the funds go + directly to that key. + */ + STATIC_REMOTE_KEY = 2; + + /* + A channel that uses a commitment format that has anchor outputs on the + commitments, allowing fee bumping after a force close transaction has + been broadcast. + */ + ANCHORS = 3; + + /* + A channel that uses a commitment type that builds upon the anchors + commitment format, but in addition requires a CLTV clause to spend outputs + paying to the channel initiator. This is intended for use on leased channels + to guarantee that the channel initiator has no incentives to close a leased + channel before its maturity date. + */ + SCRIPT_ENFORCED_LEASE = 4; + + /* + A channel that uses musig2 for the funding output, and the new tapscript + features where relevant. + */ + // TODO(roasbeef): need script enforce mirror type for the above as well? + SIMPLE_TAPROOT = 5; +} + +message ChannelConstraints { + /* + The CSV delay expressed in relative blocks. If the channel is force closed, + we will need to wait for this many blocks before we can regain our funds. + */ + uint32 csv_delay = 1; + + // The minimum satoshis this node is required to reserve in its balance. + uint64 chan_reserve_sat = 2; + + // The dust limit (in satoshis) of the initiator's commitment tx. + uint64 dust_limit_sat = 3; + + // The maximum amount of coins in millisatoshis that can be pending in this + // channel. + uint64 max_pending_amt_msat = 4; + + // The smallest HTLC in millisatoshis that the initiator will accept. + uint64 min_htlc_msat = 5; + + // The total number of incoming HTLC's that the initiator will accept. + uint32 max_accepted_htlcs = 6; +} + +message Channel { + // Whether this channel is active or not + bool active = 1; + + // The identity pubkey of the remote node + string remote_pubkey = 2; + + /* + The outpoint (txid:index) of the funding transaction. With this value, Bob + will be able to generate a signature for Alice's version of the commitment + transaction. + */ + string channel_point = 3; + + /* + The unique channel ID for the channel. The first 3 bytes are the block + height, the next 3 the index within the block, and the last 2 bytes are the + output index for the channel. + */ + uint64 chan_id = 4 [jstype = JS_STRING]; + + // The total amount of funds held in this channel + int64 capacity = 5; + + // This node's current balance in this channel + int64 local_balance = 6; + + // The counterparty's current balance in this channel + int64 remote_balance = 7; + + /* + The amount calculated to be paid in fees for the current set of commitment + transactions. The fee amount is persisted with the channel in order to + allow the fee amount to be removed and recalculated with each channel state + update, including updates that happen after a system restart. + */ + int64 commit_fee = 8; + + // The weight of the commitment transaction + int64 commit_weight = 9; + + /* + The required number of satoshis per kilo-weight that the requester will pay + at all times, for both the funding transaction and commitment transaction. + This value can later be updated once the channel is open. + */ + int64 fee_per_kw = 10; + + // The unsettled balance in this channel + int64 unsettled_balance = 11; + + /* + The total number of satoshis we've sent within this channel. + */ + int64 total_satoshis_sent = 12; + + /* + The total number of satoshis we've received within this channel. + */ + int64 total_satoshis_received = 13; + + /* + The total number of updates conducted within this channel. + */ + uint64 num_updates = 14; + + /* + The list of active, uncleared HTLCs currently pending within the channel. + */ + repeated HTLC pending_htlcs = 15; + + /* + Deprecated. The CSV delay expressed in relative blocks. If the channel is + force closed, we will need to wait for this many blocks before we can regain + our funds. + */ + uint32 csv_delay = 16 [deprecated = true]; + + // Whether this channel is advertised to the network or not. + bool private = 17; + + // True if we were the ones that created the channel. + bool initiator = 18; + + // A set of flags showing the current state of the channel. + string chan_status_flags = 19; + + // Deprecated. The minimum satoshis this node is required to reserve in its + // balance. + int64 local_chan_reserve_sat = 20 [deprecated = true]; + + /* + Deprecated. The minimum satoshis the other node is required to reserve in + its balance. + */ + int64 remote_chan_reserve_sat = 21 [deprecated = true]; + + // Deprecated. Use commitment_type. + bool static_remote_key = 22 [deprecated = true]; + + // The commitment type used by this channel. + CommitmentType commitment_type = 26; + + /* + The number of seconds that the channel has been monitored by the channel + scoring system. Scores are currently not persisted, so this value may be + less than the lifetime of the channel [EXPERIMENTAL]. + */ + int64 lifetime = 23; + + /* + The number of seconds that the remote peer has been observed as being online + by the channel scoring system over the lifetime of the channel + [EXPERIMENTAL]. + */ + int64 uptime = 24; + + /* + Close address is the address that we will enforce payout to on cooperative + close if the channel was opened utilizing option upfront shutdown. This + value can be set on channel open by setting close_address in an open channel + request. If this value is not set, you can still choose a payout address by + cooperatively closing with the delivery_address field set. + */ + string close_address = 25; + + /* + The amount that the initiator of the channel optionally pushed to the remote + party on channel open. This amount will be zero if the channel initiator did + not push any funds to the remote peer. If the initiator field is true, we + pushed this amount to our peer, if it is false, the remote peer pushed this + amount to us. + */ + uint64 push_amount_sat = 27; + + /* + This uint32 indicates if this channel is to be considered 'frozen'. A + frozen channel doest not allow a cooperative channel close by the + initiator. The thaw_height is the height that this restriction stops + applying to the channel. This field is optional, not setting it or using a + value of zero will mean the channel has no additional restrictions. The + height can be interpreted in two ways: as a relative height if the value is + less than 500,000, or as an absolute height otherwise. + */ + uint32 thaw_height = 28; + + // List constraints for the local node. + ChannelConstraints local_constraints = 29; + + // List constraints for the remote node. + ChannelConstraints remote_constraints = 30; + + /* + This lists out the set of alias short channel ids that exist for a channel. + This may be empty. + */ + repeated uint64 alias_scids = 31; + + // Whether or not this is a zero-conf channel. + bool zero_conf = 32; + + // This is the confirmed / on-chain zero-conf SCID. + uint64 zero_conf_confirmed_scid = 33; + + // The configured alias name of our peer. + string peer_alias = 34; + + // This is the peer SCID alias. + uint64 peer_scid_alias = 35 [jstype = JS_STRING]; + + /* + An optional note-to-self to go along with the channel containing some + useful information. This is only ever stored locally and in no way impacts + the channel's operation. + */ + string memo = 36; +} + +message ListChannelsRequest { + bool active_only = 1; + bool inactive_only = 2; + bool public_only = 3; + bool private_only = 4; + + /* + Filters the response for channels with a target peer's pubkey. If peer is + empty, all channels will be returned. + */ + bytes peer = 5; + + // Informs the server if the peer alias lookup per channel should be + // enabled. It is turned off by default in order to avoid degradation of + // performance for existing clients. + bool peer_alias_lookup = 6; +} +message ListChannelsResponse { + // The list of active channels + repeated Channel channels = 11; +} + +message AliasMap { + /* + For non-zero-conf channels, this is the confirmed SCID. Otherwise, this is + the first assigned "base" alias. + */ + uint64 base_scid = 1; + + // The set of all aliases stored for the base SCID. + repeated uint64 aliases = 2; +} +message ListAliasesRequest { +} +message ListAliasesResponse { + repeated AliasMap alias_maps = 1; +} + +enum Initiator { + INITIATOR_UNKNOWN = 0; + INITIATOR_LOCAL = 1; + INITIATOR_REMOTE = 2; + INITIATOR_BOTH = 3; +} + +message ChannelCloseSummary { + // The outpoint (txid:index) of the funding transaction. + string channel_point = 1; + + // The unique channel ID for the channel. + uint64 chan_id = 2 [jstype = JS_STRING]; + + // The hash of the genesis block that this channel resides within. + string chain_hash = 3; + + // The txid of the transaction which ultimately closed this channel. + string closing_tx_hash = 4; + + // Public key of the remote peer that we formerly had a channel with. + string remote_pubkey = 5; + + // Total capacity of the channel. + int64 capacity = 6; + + // Height at which the funding transaction was spent. + uint32 close_height = 7; + + // Settled balance at the time of channel closure + int64 settled_balance = 8; + + // The sum of all the time-locked outputs at the time of channel closure + int64 time_locked_balance = 9; + + enum ClosureType { + COOPERATIVE_CLOSE = 0; + LOCAL_FORCE_CLOSE = 1; + REMOTE_FORCE_CLOSE = 2; + BREACH_CLOSE = 3; + FUNDING_CANCELED = 4; + ABANDONED = 5; + } + + // Details on how the channel was closed. + ClosureType close_type = 10; + + /* + Open initiator is the party that initiated opening the channel. Note that + this value may be unknown if the channel was closed before we migrated to + store open channel information after close. + */ + Initiator open_initiator = 11; + + /* + Close initiator indicates which party initiated the close. This value will + be unknown for channels that were cooperatively closed before we started + tracking cooperative close initiators. Note that this indicates which party + initiated a close, and it is possible for both to initiate cooperative or + force closes, although only one party's close will be confirmed on chain. + */ + Initiator close_initiator = 12; + + repeated Resolution resolutions = 13; + + /* + This lists out the set of alias short channel ids that existed for the + closed channel. This may be empty. + */ + repeated uint64 alias_scids = 14; + + // The confirmed SCID for a zero-conf channel. + uint64 zero_conf_confirmed_scid = 15 [jstype = JS_STRING]; +} + +enum ResolutionType { + TYPE_UNKNOWN = 0; + + // We resolved an anchor output. + ANCHOR = 1; + + /* + We are resolving an incoming htlc on chain. This if this htlc is + claimed, we swept the incoming htlc with the preimage. If it is timed + out, our peer swept the timeout path. + */ + INCOMING_HTLC = 2; + + /* + We are resolving an outgoing htlc on chain. If this htlc is claimed, + the remote party swept the htlc with the preimage. If it is timed out, + we swept it with the timeout path. + */ + OUTGOING_HTLC = 3; + + // We force closed and need to sweep our time locked commitment output. + COMMIT = 4; +} + +enum ResolutionOutcome { + // Outcome unknown. + OUTCOME_UNKNOWN = 0; + + // An output was claimed on chain. + CLAIMED = 1; + + // An output was left unclaimed on chain. + UNCLAIMED = 2; + + /* + ResolverOutcomeAbandoned indicates that an output that we did not + claim on chain, for example an anchor that we did not sweep and a + third party claimed on chain, or a htlc that we could not decode + so left unclaimed. + */ + ABANDONED = 3; + + /* + If we force closed our channel, our htlcs need to be claimed in two + stages. This outcome represents the broadcast of a timeout or success + transaction for this two stage htlc claim. + */ + FIRST_STAGE = 4; + + // A htlc was timed out on chain. + TIMEOUT = 5; +} + +message Resolution { + // The type of output we are resolving. + ResolutionType resolution_type = 1; + + // The outcome of our on chain action that resolved the outpoint. + ResolutionOutcome outcome = 2; + + // The outpoint that was spent by the resolution. + OutPoint outpoint = 3; + + // The amount that was claimed by the resolution. + uint64 amount_sat = 4; + + // The hex-encoded transaction ID of the sweep transaction that spent the + // output. + string sweep_txid = 5; +} + +message ClosedChannelsRequest { + bool cooperative = 1; + bool local_force = 2; + bool remote_force = 3; + bool breach = 4; + bool funding_canceled = 5; + bool abandoned = 6; +} + +message ClosedChannelsResponse { + repeated ChannelCloseSummary channels = 1; +} + +message Peer { + // The identity pubkey of the peer + string pub_key = 1; + + // Network address of the peer; eg `127.0.0.1:10011` + string address = 3; + + // Bytes of data transmitted to this peer + uint64 bytes_sent = 4; + + // Bytes of data transmitted from this peer + uint64 bytes_recv = 5; + + // Satoshis sent to this peer + int64 sat_sent = 6; + + // Satoshis received from this peer + int64 sat_recv = 7; + + // A channel is inbound if the counterparty initiated the channel + bool inbound = 8; + + // Ping time to this peer + int64 ping_time = 9; + + enum SyncType { + /* + Denotes that we cannot determine the peer's current sync type. + */ + UNKNOWN_SYNC = 0; + + /* + Denotes that we are actively receiving new graph updates from the peer. + */ + ACTIVE_SYNC = 1; + + /* + Denotes that we are not receiving new graph updates from the peer. + */ + PASSIVE_SYNC = 2; + + /* + Denotes that this peer is pinned into an active sync. + */ + PINNED_SYNC = 3; + } + + // The type of sync we are currently performing with this peer. + SyncType sync_type = 10; + + // Features advertised by the remote peer in their init message. + map features = 11; + + /* + The latest errors received from our peer with timestamps, limited to the 10 + most recent errors. These errors are tracked across peer connections, but + are not persisted across lnd restarts. Note that these errors are only + stored for peers that we have channels open with, to prevent peers from + spamming us with errors at no cost. + */ + repeated TimestampedError errors = 12; + + /* + The number of times we have recorded this peer going offline or coming + online, recorded across restarts. Note that this value is decreased over + time if the peer has not recently flapped, so that we can forgive peers + with historically high flap counts. + */ + int32 flap_count = 13; + + /* + The timestamp of the last flap we observed for this peer. If this value is + zero, we have not observed any flaps for this peer. + */ + int64 last_flap_ns = 14; + + /* + The last ping payload the peer has sent to us. + */ + bytes last_ping_payload = 15; +} + +message TimestampedError { + // The unix timestamp in seconds when the error occurred. + uint64 timestamp = 1; + + // The string representation of the error sent by our peer. + string error = 2; +} + +message ListPeersRequest { + /* + If true, only the last error that our peer sent us will be returned with + the peer's information, rather than the full set of historic errors we have + stored. + */ + bool latest_error = 1; +} +message ListPeersResponse { + // The list of currently connected peers + repeated Peer peers = 1; +} + +message PeerEventSubscription { +} + +message PeerEvent { + // The identity pubkey of the peer. + string pub_key = 1; + + enum EventType { + PEER_ONLINE = 0; + PEER_OFFLINE = 1; + } + + EventType type = 2; +} + +message GetInfoRequest { +} +message GetInfoResponse { + // The version of the LND software that the node is running. + string version = 14; + + // The SHA1 commit hash that the daemon is compiled with. + string commit_hash = 20; + + // The identity pubkey of the current node. + string identity_pubkey = 1; + + // If applicable, the alias of the current node, e.g. "bob" + string alias = 2; + + // The color of the current node in hex code format + string color = 17; + + // Number of pending channels + uint32 num_pending_channels = 3; + + // Number of active channels + uint32 num_active_channels = 4; + + // Number of inactive channels + uint32 num_inactive_channels = 15; + + // Number of peers + uint32 num_peers = 5; + + // The node's current view of the height of the best block + uint32 block_height = 6; + + // The node's current view of the hash of the best block + string block_hash = 8; + + // Timestamp of the block best known to the wallet + int64 best_header_timestamp = 13; + + // Whether the wallet's view is synced to the main chain + bool synced_to_chain = 9; + + // Whether we consider ourselves synced with the public channel graph. + bool synced_to_graph = 18; + + /* + Whether the current node is connected to testnet. This field is + deprecated and the network field should be used instead + */ + bool testnet = 10 [deprecated = true]; + + reserved 11; + + /* + Deprecated. The only active chain is bitcoin. + A list of active chains the node is connected to + */ + repeated Chain chains = 16 [deprecated = true]; + + // The URIs of the current node. + repeated string uris = 12; + + /* + Features that our node has advertised in our init message, node + announcements and invoices. + */ + map features = 19; + + /* + Indicates whether the HTLC interceptor API is in always-on mode. + */ + bool require_htlc_interceptor = 21; + + // Indicates whether final htlc resolutions are stored on disk. + bool store_final_htlc_resolutions = 22; +} + +message GetRecoveryInfoRequest { +} +message GetRecoveryInfoResponse { + // Whether the wallet is in recovery mode + bool recovery_mode = 1; + + // Whether the wallet recovery progress is finished + bool recovery_finished = 2; + + // The recovery progress, ranging from 0 to 1. + double progress = 3; +} + +message Chain { + // Deprecated. The chain is now always assumed to be bitcoin. + // The blockchain the node is on (must be bitcoin) + string chain = 1 [deprecated = true]; + + // The network the node is on (eg regtest, testnet, mainnet) + string network = 2; +} + +message ConfirmationUpdate { + bytes block_sha = 1; + int32 block_height = 2; + + uint32 num_confs_left = 3; +} + +message ChannelOpenUpdate { + ChannelPoint channel_point = 1; +} + +message ChannelCloseUpdate { + bytes closing_txid = 1; + + bool success = 2; +} + +message CloseChannelRequest { + /* + The outpoint (txid:index) of the funding transaction. With this value, Bob + will be able to generate a signature for Alice's version of the commitment + transaction. + */ + ChannelPoint channel_point = 1; + + // If true, then the channel will be closed forcibly. This means the + // current commitment transaction will be signed and broadcast. + bool force = 2; + + // The target number of blocks that the closure transaction should be + // confirmed by. + int32 target_conf = 3; + + // Deprecated, use sat_per_vbyte. + // A manual fee rate set in sat/vbyte that should be used when crafting the + // closure transaction. + int64 sat_per_byte = 4 [deprecated = true]; + + /* + An optional address to send funds to in the case of a cooperative close. + If the channel was opened with an upfront shutdown script and this field + is set, the request to close will fail because the channel must pay out + to the upfront shutdown addresss. + */ + string delivery_address = 5; + + // A manual fee rate set in sat/vbyte that should be used when crafting the + // closure transaction. + uint64 sat_per_vbyte = 6; + + // The maximum fee rate the closer is willing to pay. + // + // NOTE: This field is only respected if we're the initiator of the channel. + uint64 max_fee_per_vbyte = 7; +} + +message CloseStatusUpdate { + oneof update { + PendingUpdate close_pending = 1; + ChannelCloseUpdate chan_close = 3; + } +} + +message PendingUpdate { + bytes txid = 1; + uint32 output_index = 2; +} + +message ReadyForPsbtFunding { + /* + The P2WSH address of the channel funding multisig address that the below + specified amount in satoshis needs to be sent to. + */ + string funding_address = 1; + + /* + The exact amount in satoshis that needs to be sent to the above address to + fund the pending channel. + */ + int64 funding_amount = 2; + + /* + A raw PSBT that contains the pending channel output. If a base PSBT was + provided in the PsbtShim, this is the base PSBT with one additional output. + If no base PSBT was specified, this is an otherwise empty PSBT with exactly + one output. + */ + bytes psbt = 3; +} + +message BatchOpenChannelRequest { + // The list of channels to open. + repeated BatchOpenChannel channels = 1; + + // The target number of blocks that the funding transaction should be + // confirmed by. + int32 target_conf = 2; + + // A manual fee rate set in sat/vByte that should be used when crafting the + // funding transaction. + int64 sat_per_vbyte = 3; + + // The minimum number of confirmations each one of your outputs used for + // the funding transaction must satisfy. + int32 min_confs = 4; + + // Whether unconfirmed outputs should be used as inputs for the funding + // transaction. + bool spend_unconfirmed = 5; + + // An optional label for the batch transaction, limited to 500 characters. + string label = 6; +} + +message BatchOpenChannel { + // The pubkey of the node to open a channel with. When using REST, this + // field must be encoded as base64. + bytes node_pubkey = 1; + + // The number of satoshis the wallet should commit to the channel. + int64 local_funding_amount = 2; + + // The number of satoshis to push to the remote side as part of the initial + // commitment state. + int64 push_sat = 3; + + // Whether this channel should be private, not announced to the greater + // network. + bool private = 4; + + // The minimum value in millisatoshi we will require for incoming HTLCs on + // the channel. + int64 min_htlc_msat = 5; + + // The delay we require on the remote's commitment transaction. If this is + // not set, it will be scaled automatically with the channel size. + uint32 remote_csv_delay = 6; + + /* + Close address is an optional address which specifies the address to which + funds should be paid out to upon cooperative close. This field may only be + set if the peer supports the option upfront feature bit (call listpeers + to check). The remote peer will only accept cooperative closes to this + address if it is set. + + Note: If this value is set on channel creation, you will *not* be able to + cooperatively close out to a different address. + */ + string close_address = 7; + + /* + An optional, unique identifier of 32 random bytes that will be used as the + pending channel ID to identify the channel while it is in the pre-pending + state. + */ + bytes pending_chan_id = 8; + + /* + The explicit commitment type to use. Note this field will only be used if + the remote peer supports explicit channel negotiation. + */ + CommitmentType commitment_type = 9; + + /* + The maximum amount of coins in millisatoshi that can be pending within + the channel. It only applies to the remote party. + */ + uint64 remote_max_value_in_flight_msat = 10; + + /* + The maximum number of concurrent HTLCs we will allow the remote party to add + to the commitment transaction. + */ + uint32 remote_max_htlcs = 11; + + /* + Max local csv is the maximum csv delay we will allow for our own commitment + transaction. + */ + uint32 max_local_csv = 12; + + /* + If this is true, then a zero-conf channel open will be attempted. + */ + bool zero_conf = 13; + + /* + If this is true, then an option-scid-alias channel-type open will be + attempted. + */ + bool scid_alias = 14; + + /* + The base fee charged regardless of the number of milli-satoshis sent. + */ + uint64 base_fee = 15; + + /* + The fee rate in ppm (parts per million) that will be charged in + proportion of the value of each forwarded HTLC. + */ + uint64 fee_rate = 16; + + /* + If use_base_fee is true the open channel announcement will update the + channel base fee with the value specified in base_fee. In the case of + a base_fee of 0 use_base_fee is needed downstream to distinguish whether + to use the default base fee value specified in the config or 0. + */ + bool use_base_fee = 17; + + /* + If use_fee_rate is true the open channel announcement will update the + channel fee rate with the value specified in fee_rate. In the case of + a fee_rate of 0 use_fee_rate is needed downstream to distinguish whether + to use the default fee rate value specified in the config or 0. + */ + bool use_fee_rate = 18; + + /* + The number of satoshis we require the remote peer to reserve. This value, + if specified, must be above the dust limit and below 20% of the channel + capacity. + */ + uint64 remote_chan_reserve_sat = 19; + + /* + An optional note-to-self to go along with the channel containing some + useful information. This is only ever stored locally and in no way impacts + the channel's operation. + */ + string memo = 20; +} + +message BatchOpenChannelResponse { + repeated PendingUpdate pending_channels = 1; +} + +message OpenChannelRequest { + // A manual fee rate set in sat/vbyte that should be used when crafting the + // funding transaction. + uint64 sat_per_vbyte = 1; + + /* + The pubkey of the node to open a channel with. When using REST, this field + must be encoded as base64. + */ + bytes node_pubkey = 2; + + /* + The hex encoded pubkey of the node to open a channel with. Deprecated now + that the REST gateway supports base64 encoding of bytes fields. + */ + string node_pubkey_string = 3 [deprecated = true]; + + // The number of satoshis the wallet should commit to the channel + int64 local_funding_amount = 4; + + // The number of satoshis to push to the remote side as part of the initial + // commitment state + int64 push_sat = 5; + + // The target number of blocks that the funding transaction should be + // confirmed by. + int32 target_conf = 6; + + // Deprecated, use sat_per_vbyte. + // A manual fee rate set in sat/vbyte that should be used when crafting the + // funding transaction. + int64 sat_per_byte = 7 [deprecated = true]; + + // Whether this channel should be private, not announced to the greater + // network. + bool private = 8; + + // The minimum value in millisatoshi we will require for incoming HTLCs on + // the channel. + int64 min_htlc_msat = 9; + + // The delay we require on the remote's commitment transaction. If this is + // not set, it will be scaled automatically with the channel size. + uint32 remote_csv_delay = 10; + + // The minimum number of confirmations each one of your outputs used for + // the funding transaction must satisfy. + int32 min_confs = 11; + + // Whether unconfirmed outputs should be used as inputs for the funding + // transaction. + bool spend_unconfirmed = 12; + + /* + Close address is an optional address which specifies the address to which + funds should be paid out to upon cooperative close. This field may only be + set if the peer supports the option upfront feature bit (call listpeers + to check). The remote peer will only accept cooperative closes to this + address if it is set. + + Note: If this value is set on channel creation, you will *not* be able to + cooperatively close out to a different address. + */ + string close_address = 13; + + /* + Funding shims are an optional argument that allow the caller to intercept + certain funding functionality. For example, a shim can be provided to use a + particular key for the commitment key (ideally cold) rather than use one + that is generated by the wallet as normal, or signal that signing will be + carried out in an interactive manner (PSBT based). + */ + FundingShim funding_shim = 14; + + /* + The maximum amount of coins in millisatoshi that can be pending within + the channel. It only applies to the remote party. + */ + uint64 remote_max_value_in_flight_msat = 15; + + /* + The maximum number of concurrent HTLCs we will allow the remote party to add + to the commitment transaction. + */ + uint32 remote_max_htlcs = 16; + + /* + Max local csv is the maximum csv delay we will allow for our own commitment + transaction. + */ + uint32 max_local_csv = 17; + + /* + The explicit commitment type to use. Note this field will only be used if + the remote peer supports explicit channel negotiation. + */ + CommitmentType commitment_type = 18; + + /* + If this is true, then a zero-conf channel open will be attempted. + */ + bool zero_conf = 19; + + /* + If this is true, then an option-scid-alias channel-type open will be + attempted. + */ + bool scid_alias = 20; + + /* + The base fee charged regardless of the number of milli-satoshis sent. + */ + uint64 base_fee = 21; + + /* + The fee rate in ppm (parts per million) that will be charged in + proportion of the value of each forwarded HTLC. + */ + uint64 fee_rate = 22; + + /* + If use_base_fee is true the open channel announcement will update the + channel base fee with the value specified in base_fee. In the case of + a base_fee of 0 use_base_fee is needed downstream to distinguish whether + to use the default base fee value specified in the config or 0. + */ + bool use_base_fee = 23; + + /* + If use_fee_rate is true the open channel announcement will update the + channel fee rate with the value specified in fee_rate. In the case of + a fee_rate of 0 use_fee_rate is needed downstream to distinguish whether + to use the default fee rate value specified in the config or 0. + */ + bool use_fee_rate = 24; + + /* + The number of satoshis we require the remote peer to reserve. This value, + if specified, must be above the dust limit and below 20% of the channel + capacity. + */ + uint64 remote_chan_reserve_sat = 25; + + /* + If set, then lnd will attempt to commit all the coins under control of the + internal wallet to open the channel, and the LocalFundingAmount field must + be zero and is ignored. + */ + bool fund_max = 26; + + /* + An optional note-to-self to go along with the channel containing some + useful information. This is only ever stored locally and in no way impacts + the channel's operation. + */ + string memo = 27; + + /* + A list of selected outpoints that are allocated for channel funding. + */ + repeated OutPoint outpoints = 28; +} +message OpenStatusUpdate { + oneof update { + /* + Signals that the channel is now fully negotiated and the funding + transaction published. + */ + PendingUpdate chan_pending = 1; + + /* + Signals that the channel's funding transaction has now reached the + required number of confirmations on chain and can be used. + */ + ChannelOpenUpdate chan_open = 3; + + /* + Signals that the funding process has been suspended and the construction + of a PSBT that funds the channel PK script is now required. + */ + ReadyForPsbtFunding psbt_fund = 5; + } + + /* + The pending channel ID of the created channel. This value may be used to + further the funding flow manually via the FundingStateStep method. + */ + bytes pending_chan_id = 4; +} + +message KeyLocator { + // The family of key being identified. + int32 key_family = 1; + + // The precise index of the key being identified. + int32 key_index = 2; +} + +message KeyDescriptor { + /* + The raw bytes of the key being identified. + */ + bytes raw_key_bytes = 1; + + /* + The key locator that identifies which key to use for signing. + */ + KeyLocator key_loc = 2; +} + +message ChanPointShim { + /* + The size of the pre-crafted output to be used as the channel point for this + channel funding. + */ + int64 amt = 1; + + // The target channel point to refrence in created commitment transactions. + ChannelPoint chan_point = 2; + + // Our local key to use when creating the multi-sig output. + KeyDescriptor local_key = 3; + + // The key of the remote party to use when creating the multi-sig output. + bytes remote_key = 4; + + /* + If non-zero, then this will be used as the pending channel ID on the wire + protocol to initate the funding request. This is an optional field, and + should only be set if the responder is already expecting a specific pending + channel ID. + */ + bytes pending_chan_id = 5; + + /* + This uint32 indicates if this channel is to be considered 'frozen'. A frozen + channel does not allow a cooperative channel close by the initiator. The + thaw_height is the height that this restriction stops applying to the + channel. The height can be interpreted in two ways: as a relative height if + the value is less than 500,000, or as an absolute height otherwise. + */ + uint32 thaw_height = 6; + + /* + Indicates that the funding output is using a MuSig2 multi-sig output. + */ + bool musig2 = 7; +} + +message PsbtShim { + /* + A unique identifier of 32 random bytes that will be used as the pending + channel ID to identify the PSBT state machine when interacting with it and + on the wire protocol to initiate the funding request. + */ + bytes pending_chan_id = 1; + + /* + An optional base PSBT the new channel output will be added to. If this is + non-empty, it must be a binary serialized PSBT. + */ + bytes base_psbt = 2; + + /* + If a channel should be part of a batch (multiple channel openings in one + transaction), it can be dangerous if the whole batch transaction is + published too early before all channel opening negotiations are completed. + This flag prevents this particular channel from broadcasting the transaction + after the negotiation with the remote peer. In a batch of channel openings + this flag should be set to true for every channel but the very last. + */ + bool no_publish = 3; +} + +message FundingShim { + oneof shim { + /* + A channel shim where the channel point was fully constructed outside + of lnd's wallet and the transaction might already be published. + */ + ChanPointShim chan_point_shim = 1; + + /* + A channel shim that uses a PSBT to fund and sign the channel funding + transaction. + */ + PsbtShim psbt_shim = 2; + } +} + +message FundingShimCancel { + // The pending channel ID of the channel to cancel the funding shim for. + bytes pending_chan_id = 1; +} + +message FundingPsbtVerify { + /* + The funded but not yet signed PSBT that sends the exact channel capacity + amount to the PK script returned in the open channel message in a previous + step. + */ + bytes funded_psbt = 1; + + // The pending channel ID of the channel to get the PSBT for. + bytes pending_chan_id = 2; + + /* + Can only be used if the no_publish flag was set to true in the OpenChannel + call meaning that the caller is solely responsible for publishing the final + funding transaction. If skip_finalize is set to true then lnd will not wait + for a FundingPsbtFinalize state step and instead assumes that a transaction + with the same TXID as the passed in PSBT will eventually confirm. + IT IS ABSOLUTELY IMPERATIVE that the TXID of the transaction that is + eventually published does have the _same TXID_ as the verified PSBT. That + means no inputs or outputs can change, only signatures can be added. If the + TXID changes between this call and the publish step then the channel will + never be created and the funds will be in limbo. + */ + bool skip_finalize = 3; +} + +message FundingPsbtFinalize { + /* + The funded PSBT that contains all witness data to send the exact channel + capacity amount to the PK script returned in the open channel message in a + previous step. Cannot be set at the same time as final_raw_tx. + */ + bytes signed_psbt = 1; + + // The pending channel ID of the channel to get the PSBT for. + bytes pending_chan_id = 2; + + /* + As an alternative to the signed PSBT with all witness data, the final raw + wire format transaction can also be specified directly. Cannot be set at the + same time as signed_psbt. + */ + bytes final_raw_tx = 3; +} + +message FundingTransitionMsg { + oneof trigger { + /* + The funding shim to register. This should be used before any + channel funding has began by the remote party, as it is intended as a + preparatory step for the full channel funding. + */ + FundingShim shim_register = 1; + + // Used to cancel an existing registered funding shim. + FundingShimCancel shim_cancel = 2; + + /* + Used to continue a funding flow that was initiated to be executed + through a PSBT. This step verifies that the PSBT contains the correct + outputs to fund the channel. + */ + FundingPsbtVerify psbt_verify = 3; + + /* + Used to continue a funding flow that was initiated to be executed + through a PSBT. This step finalizes the funded and signed PSBT, finishes + negotiation with the peer and finally publishes the resulting funding + transaction. + */ + FundingPsbtFinalize psbt_finalize = 4; + } +} + +message FundingStateStepResp { +} + +message PendingHTLC { + // The direction within the channel that the htlc was sent + bool incoming = 1; + + // The total value of the htlc + int64 amount = 2; + + // The final output to be swept back to the user's wallet + string outpoint = 3; + + // The next block height at which we can spend the current stage + uint32 maturity_height = 4; + + /* + The number of blocks remaining until the current stage can be swept. + Negative values indicate how many blocks have passed since becoming + mature. + */ + int32 blocks_til_maturity = 5; + + // Indicates whether the htlc is in its first or second stage of recovery + uint32 stage = 6; +} + +message PendingChannelsRequest { +} +message PendingChannelsResponse { + message PendingChannel { + string remote_node_pub = 1; + string channel_point = 2; + + int64 capacity = 3; + + int64 local_balance = 4; + int64 remote_balance = 5; + + // The minimum satoshis this node is required to reserve in its + // balance. + int64 local_chan_reserve_sat = 6; + + /* + The minimum satoshis the other node is required to reserve in its + balance. + */ + int64 remote_chan_reserve_sat = 7; + + // The party that initiated opening the channel. + Initiator initiator = 8; + + // The commitment type used by this channel. + CommitmentType commitment_type = 9; + + // Total number of forwarding packages created in this channel. + int64 num_forwarding_packages = 10; + + // A set of flags showing the current state of the channel. + string chan_status_flags = 11; + + // Whether this channel is advertised to the network or not. + bool private = 12; + + /* + An optional note-to-self to go along with the channel containing some + useful information. This is only ever stored locally and in no way + impacts the channel's operation. + */ + string memo = 13; + } + + message PendingOpenChannel { + // The pending channel + PendingChannel channel = 1; + + /* + The amount calculated to be paid in fees for the current set of + commitment transactions. The fee amount is persisted with the channel + in order to allow the fee amount to be removed and recalculated with + each channel state update, including updates that happen after a system + restart. + */ + int64 commit_fee = 4; + + // The weight of the commitment transaction + int64 commit_weight = 5; + + /* + The required number of satoshis per kilo-weight that the requester will + pay at all times, for both the funding transaction and commitment + transaction. This value can later be updated once the channel is open. + */ + int64 fee_per_kw = 6; + + // Previously used for confirmation_height. Do not reuse. + reserved 2; + + // The number of blocks until the funding transaction is considered + // expired. If this value gets close to zero, there is a risk that the + // channel funding will be canceled by the channel responder. The + // channel should be fee bumped using CPFP (see walletrpc.BumpFee) to + // ensure that the channel confirms in time. Otherwise a force-close + // will be necessary if the channel confirms after the funding + // transaction expires. A negative value means the channel responder has + // very likely canceled the funding and the channel will never become + // fully operational. + int32 funding_expiry_blocks = 3; + } + + message WaitingCloseChannel { + // The pending channel waiting for closing tx to confirm + PendingChannel channel = 1; + + // The balance in satoshis encumbered in this channel + int64 limbo_balance = 2; + + /* + A list of valid commitment transactions. Any of these can confirm at + this point. + */ + Commitments commitments = 3; + + // The transaction id of the closing transaction + string closing_txid = 4; + } + + message Commitments { + // Hash of the local version of the commitment tx. + string local_txid = 1; + + // Hash of the remote version of the commitment tx. + string remote_txid = 2; + + // Hash of the remote pending version of the commitment tx. + string remote_pending_txid = 3; + + /* + The amount in satoshis calculated to be paid in fees for the local + commitment. + */ + uint64 local_commit_fee_sat = 4; + + /* + The amount in satoshis calculated to be paid in fees for the remote + commitment. + */ + uint64 remote_commit_fee_sat = 5; + + /* + The amount in satoshis calculated to be paid in fees for the remote + pending commitment. + */ + uint64 remote_pending_commit_fee_sat = 6; + } + + message ClosedChannel { + // The pending channel to be closed + PendingChannel channel = 1; + + // The transaction id of the closing transaction + string closing_txid = 2; + } + + message ForceClosedChannel { + // The pending channel to be force closed + PendingChannel channel = 1; + + // The transaction id of the closing transaction + string closing_txid = 2; + + // The balance in satoshis encumbered in this pending channel + int64 limbo_balance = 3; + + // The height at which funds can be swept into the wallet + uint32 maturity_height = 4; + + /* + Remaining # of blocks until the commitment output can be swept. + Negative values indicate how many blocks have passed since becoming + mature. + */ + int32 blocks_til_maturity = 5; + + // The total value of funds successfully recovered from this channel + int64 recovered_balance = 6; + + repeated PendingHTLC pending_htlcs = 8; + + /* + There are three resolution states for the anchor: + limbo, lost and recovered. Derive the current state + from the limbo and recovered balances. + */ + enum AnchorState { + // The recovered_balance is zero and limbo_balance is non-zero. + LIMBO = 0; + // The recovered_balance is non-zero. + RECOVERED = 1; + // A state that is neither LIMBO nor RECOVERED. + LOST = 2; + } + + AnchorState anchor = 9; + } + + // The balance in satoshis encumbered in pending channels + int64 total_limbo_balance = 1; + + // Channels pending opening + repeated PendingOpenChannel pending_open_channels = 2; + + /* + Deprecated: Channels pending closing previously contained cooperatively + closed channels with a single confirmation. These channels are now + considered closed from the time we see them on chain. + */ + repeated ClosedChannel pending_closing_channels = 3 [deprecated = true]; + + // Channels pending force closing + repeated ForceClosedChannel pending_force_closing_channels = 4; + + // Channels waiting for closing tx to confirm + repeated WaitingCloseChannel waiting_close_channels = 5; +} + +message ChannelEventSubscription { +} + +message ChannelEventUpdate { + oneof channel { + Channel open_channel = 1; + ChannelCloseSummary closed_channel = 2; + ChannelPoint active_channel = 3; + ChannelPoint inactive_channel = 4; + PendingUpdate pending_open_channel = 6; + ChannelPoint fully_resolved_channel = 7; + } + + enum UpdateType { + OPEN_CHANNEL = 0; + CLOSED_CHANNEL = 1; + ACTIVE_CHANNEL = 2; + INACTIVE_CHANNEL = 3; + PENDING_OPEN_CHANNEL = 4; + FULLY_RESOLVED_CHANNEL = 5; + } + + UpdateType type = 5; +} + +message WalletAccountBalance { + // The confirmed balance of the account (with >= 1 confirmations). + int64 confirmed_balance = 1; + + // The unconfirmed balance of the account (with 0 confirmations). + int64 unconfirmed_balance = 2; +} + +message WalletBalanceRequest { + // The wallet account the balance is shown for. + // If this is not specified, the balance of the "default" account is shown. + string account = 1; +} + +message WalletBalanceResponse { + // The balance of the wallet + int64 total_balance = 1; + + // The confirmed balance of a wallet(with >= 1 confirmations) + int64 confirmed_balance = 2; + + // The unconfirmed balance of a wallet(with 0 confirmations) + int64 unconfirmed_balance = 3; + + // The total amount of wallet UTXOs held in outputs that are locked for + // other usage. + int64 locked_balance = 5; + + // The amount of reserve required. + int64 reserved_balance_anchor_chan = 6; + + // A mapping of each wallet account's name to its balance. + map account_balance = 4; +} + +message Amount { + // Value denominated in satoshis. + uint64 sat = 1; + + // Value denominated in milli-satoshis. + uint64 msat = 2; +} + +message ChannelBalanceRequest { +} +message ChannelBalanceResponse { + // Deprecated. Sum of channels balances denominated in satoshis + int64 balance = 1 [deprecated = true]; + + // Deprecated. Sum of channels pending balances denominated in satoshis + int64 pending_open_balance = 2 [deprecated = true]; + + // Sum of channels local balances. + Amount local_balance = 3; + + // Sum of channels remote balances. + Amount remote_balance = 4; + + // Sum of channels local unsettled balances. + Amount unsettled_local_balance = 5; + + // Sum of channels remote unsettled balances. + Amount unsettled_remote_balance = 6; + + // Sum of channels pending local balances. + Amount pending_open_local_balance = 7; + + // Sum of channels pending remote balances. + Amount pending_open_remote_balance = 8; +} + +message QueryRoutesRequest { + // The 33-byte hex-encoded public key for the payment destination + string pub_key = 1; + + /* + The amount to send expressed in satoshis. + + The fields amt and amt_msat are mutually exclusive. + */ + int64 amt = 2; + + /* + The amount to send expressed in millisatoshis. + + The fields amt and amt_msat are mutually exclusive. + */ + int64 amt_msat = 12; + + reserved 3; + + /* + An optional CLTV delta from the current height that should be used for the + timelock of the final hop. Note that unlike SendPayment, QueryRoutes does + not add any additional block padding on top of final_ctlv_delta. This + padding of a few blocks needs to be added manually or otherwise failures may + happen when a block comes in while the payment is in flight. + + Note: must not be set if making a payment to a blinded path (delta is + set by the aggregate parameters provided by blinded_payment_paths) + */ + int32 final_cltv_delta = 4; + + /* + The maximum number of satoshis that will be paid as a fee of the payment. + This value can be represented either as a percentage of the amount being + sent, or as a fixed amount of the maximum fee the user is willing the pay to + send the payment. If not specified, lnd will use a default value of 100% + fees for small amounts (<=1k sat) or 5% fees for larger amounts. + */ + FeeLimit fee_limit = 5; + + /* + A list of nodes to ignore during path finding. When using REST, these fields + must be encoded as base64. + */ + repeated bytes ignored_nodes = 6; + + /* + Deprecated. A list of edges to ignore during path finding. + */ + repeated EdgeLocator ignored_edges = 7 [deprecated = true]; + + /* + The source node where the request route should originated from. If empty, + self is assumed. + */ + string source_pub_key = 8; + + /* + If set to true, edge probabilities from mission control will be used to get + the optimal route. + */ + bool use_mission_control = 9; + + /* + A list of directed node pairs that will be ignored during path finding. + */ + repeated NodePair ignored_pairs = 10; + + /* + An optional maximum total time lock for the route. If the source is empty or + ourselves, this should not exceed lnd's `--max-cltv-expiry` setting. If + zero, then the value of `--max-cltv-expiry` is used as the limit. + */ + uint32 cltv_limit = 11; + + /* + An optional field that can be used to pass an arbitrary set of TLV records + to a peer which understands the new records. This can be used to pass + application specific data during the payment attempt. If the destination + does not support the specified records, an error will be returned. + Record types are required to be in the custom range >= 65536. When using + REST, the values must be encoded as base64. + */ + map dest_custom_records = 13; + + /* + The channel id of the channel that must be taken to the first hop. If zero, + any channel may be used. + */ + uint64 outgoing_chan_id = 14 [jstype = JS_STRING]; + + /* + The pubkey of the last hop of the route. If empty, any hop may be used. + */ + bytes last_hop_pubkey = 15; + + /* + Optional route hints to reach the destination through private channels. + */ + repeated lnrpc.RouteHint route_hints = 16; + + /* + An optional blinded path(s) to reach the destination. Note that the + introduction node must be provided as the first hop in the route. + */ + repeated BlindedPaymentPath blinded_payment_paths = 19; + + /* + Features assumed to be supported by the final node. All transitive feature + dependencies must also be set properly. For a given feature bit pair, either + optional or remote may be set, but not both. If this field is nil or empty, + the router will try to load destination features from the graph as a + fallback. + + Note: must not be set if making a payment to a blinded route (features + are provided in blinded_payment_paths). + */ + repeated lnrpc.FeatureBit dest_features = 17; + + /* + The time preference for this payment. Set to -1 to optimize for fees + only, to 1 to optimize for reliability only or a value inbetween for a mix. + */ + double time_pref = 18; +} + +message NodePair { + /* + The sending node of the pair. When using REST, this field must be encoded as + base64. + */ + bytes from = 1; + + /* + The receiving node of the pair. When using REST, this field must be encoded + as base64. + */ + bytes to = 2; +} + +message EdgeLocator { + // The short channel id of this edge. + uint64 channel_id = 1 [jstype = JS_STRING]; + + /* + The direction of this edge. If direction_reverse is false, the direction + of this edge is from the channel endpoint with the lexicographically smaller + pub key to the endpoint with the larger pub key. If direction_reverse is + is true, the edge goes the other way. + */ + bool direction_reverse = 2; +} + +message QueryRoutesResponse { + /* + The route that results from the path finding operation. This is still a + repeated field to retain backwards compatibility. + */ + repeated Route routes = 1; + + /* + The success probability of the returned route based on the current mission + control state. [EXPERIMENTAL] + */ + double success_prob = 2; +} + +message Hop { + /* + The unique channel ID for the channel. The first 3 bytes are the block + height, the next 3 the index within the block, and the last 2 bytes are the + output index for the channel. + */ + uint64 chan_id = 1 [jstype = JS_STRING]; + int64 chan_capacity = 2 [deprecated = true]; + int64 amt_to_forward = 3 [deprecated = true]; + int64 fee = 4 [deprecated = true]; + uint32 expiry = 5; + int64 amt_to_forward_msat = 6; + int64 fee_msat = 7; + + /* + An optional public key of the hop. If the public key is given, the payment + can be executed without relying on a copy of the channel graph. + */ + string pub_key = 8; + + /* + If set to true, then this hop will be encoded using the new variable length + TLV format. Note that if any custom tlv_records below are specified, then + this field MUST be set to true for them to be encoded properly. + */ + bool tlv_payload = 9 [deprecated = true]; + + /* + An optional TLV record that signals the use of an MPP payment. If present, + the receiver will enforce that the same mpp_record is included in the final + hop payload of all non-zero payments in the HTLC set. If empty, a regular + single-shot payment is or was attempted. + */ + MPPRecord mpp_record = 10; + + /* + An optional TLV record that signals the use of an AMP payment. If present, + the receiver will treat all received payments including the same + (payment_addr, set_id) pair as being part of one logical payment. The + payment will be settled by XORing the root_share's together and deriving the + child hashes and preimages according to BOLT XX. Must be used in conjunction + with mpp_record. + */ + AMPRecord amp_record = 12; + + /* + An optional set of key-value TLV records. This is useful within the context + of the SendToRoute call as it allows callers to specify arbitrary K-V pairs + to drop off at each hop within the onion. + */ + map custom_records = 11; + + // The payment metadata to send along with the payment to the payee. + bytes metadata = 13; + + /* + Blinding point is an optional blinding point included for introduction + nodes in blinded paths. This field is mandatory for hops that represents + the introduction point in a blinded path. + */ + bytes blinding_point = 14; + + /* + Encrypted data is a receiver-produced blob of data that provides hops + in a blinded route with forwarding data. As this data is encrypted by + the recipient, we will not be able to parse it - it is essentially an + arbitrary blob of data from our node's perspective. This field is + mandatory for all hops in a blinded path, including the introduction + node. + */ + bytes encrypted_data = 15; + + /* + The total amount that is sent to the recipient (possibly across multiple + HTLCs), as specified by the sender when making a payment to a blinded path. + This value is only set in the final hop payload of a blinded payment. This + value is analogous to the MPPRecord that is used for regular (non-blinded) + MPP payments. + */ + uint64 total_amt_msat = 16; +} + +message MPPRecord { + /* + A unique, random identifier used to authenticate the sender as the intended + payer of a multi-path payment. The payment_addr must be the same for all + subpayments, and match the payment_addr provided in the receiver's invoice. + The same payment_addr must be used on all subpayments. + */ + bytes payment_addr = 11; + + /* + The total amount in milli-satoshis being sent as part of a larger multi-path + payment. The caller is responsible for ensuring subpayments to the same node + and payment_hash sum exactly to total_amt_msat. The same + total_amt_msat must be used on all subpayments. + */ + int64 total_amt_msat = 10; +} + +message AMPRecord { + bytes root_share = 1; + + bytes set_id = 2; + + uint32 child_index = 3; +} + +/* +A path through the channel graph which runs over one or more channels in +succession. This struct carries all the information required to craft the +Sphinx onion packet, and send the payment along the first hop in the path. A +route is only selected as valid if all the channels have sufficient capacity to +carry the initial payment amount after fees are accounted for. +*/ +message Route { + /* + The cumulative (final) time lock across the entire route. This is the CLTV + value that should be extended to the first hop in the route. All other hops + will decrement the time-lock as advertised, leaving enough time for all + hops to wait for or present the payment preimage to complete the payment. + */ + uint32 total_time_lock = 1; + + /* + The sum of the fees paid at each hop within the final route. In the case + of a one-hop payment, this value will be zero as we don't need to pay a fee + to ourselves. + */ + int64 total_fees = 2 [deprecated = true]; + + /* + The total amount of funds required to complete a payment over this route. + This value includes the cumulative fees at each hop. As a result, the HTLC + extended to the first-hop in the route will need to have at least this many + satoshis, otherwise the route will fail at an intermediate node due to an + insufficient amount of fees. + */ + int64 total_amt = 3 [deprecated = true]; + + /* + Contains details concerning the specific forwarding details at each hop. + */ + repeated Hop hops = 4; + + /* + The total fees in millisatoshis. + */ + int64 total_fees_msat = 5; + + /* + The total amount in millisatoshis. + */ + int64 total_amt_msat = 6; +} + +message NodeInfoRequest { + // The 33-byte hex-encoded compressed public of the target node + string pub_key = 1; + + // If true, will include all known channels associated with the node. + bool include_channels = 2; +} + +message NodeInfo { + /* + An individual vertex/node within the channel graph. A node is + connected to other nodes by one or more channel edges emanating from it. As + the graph is directed, a node will also have an incoming edge attached to + it for each outgoing edge. + */ + LightningNode node = 1; + + // The total number of channels for the node. + uint32 num_channels = 2; + + // The sum of all channels capacity for the node, denominated in satoshis. + int64 total_capacity = 3; + + // A list of all public channels for the node. + repeated ChannelEdge channels = 4; +} + +/* +An individual vertex/node within the channel graph. A node is +connected to other nodes by one or more channel edges emanating from it. As the +graph is directed, a node will also have an incoming edge attached to it for +each outgoing edge. +*/ +message LightningNode { + uint32 last_update = 1; + string pub_key = 2; + string alias = 3; + repeated NodeAddress addresses = 4; + string color = 5; + map features = 6; + + // Custom node announcement tlv records. + map custom_records = 7; +} + +message NodeAddress { + string network = 1; + string addr = 2; +} + +message RoutingPolicy { + uint32 time_lock_delta = 1; + int64 min_htlc = 2; + int64 fee_base_msat = 3; + int64 fee_rate_milli_msat = 4; + bool disabled = 5; + uint64 max_htlc_msat = 6; + uint32 last_update = 7; + + // Custom channel update tlv records. + map custom_records = 8; +} + +/* +A fully authenticated channel along with all its unique attributes. +Once an authenticated channel announcement has been processed on the network, +then an instance of ChannelEdgeInfo encapsulating the channels attributes is +stored. The other portions relevant to routing policy of a channel are stored +within a ChannelEdgePolicy for each direction of the channel. +*/ +message ChannelEdge { + /* + The unique channel ID for the channel. The first 3 bytes are the block + height, the next 3 the index within the block, and the last 2 bytes are the + output index for the channel. + */ + uint64 channel_id = 1 [jstype = JS_STRING]; + string chan_point = 2; + + uint32 last_update = 3 [deprecated = true]; + + string node1_pub = 4; + string node2_pub = 5; + + int64 capacity = 6; + + RoutingPolicy node1_policy = 7; + RoutingPolicy node2_policy = 8; + + // Custom channel announcement tlv records. + map custom_records = 9; +} + +message ChannelGraphRequest { + /* + Whether unannounced channels are included in the response or not. If set, + unannounced channels are included. Unannounced channels are both private + channels, and public channels that are not yet announced to the network. + */ + bool include_unannounced = 1; +} + +// Returns a new instance of the directed channel graph. +message ChannelGraph { + // The list of `LightningNode`s in this channel graph + repeated LightningNode nodes = 1; + + // The list of `ChannelEdge`s in this channel graph + repeated ChannelEdge edges = 2; +} + +enum NodeMetricType { + UNKNOWN = 0; + BETWEENNESS_CENTRALITY = 1; +} + +message NodeMetricsRequest { + // The requested node metrics. + repeated NodeMetricType types = 1; +} + +message NodeMetricsResponse { + /* + Betweenness centrality is the sum of the ratio of shortest paths that pass + through the node for each pair of nodes in the graph (not counting paths + starting or ending at this node). + Map of node pubkey to betweenness centrality of the node. Normalized + values are in the [0,1] closed interval. + */ + map betweenness_centrality = 1; +} + +message FloatMetric { + // Arbitrary float value. + double value = 1; + + // The value normalized to [0,1] or [-1,1]. + double normalized_value = 2; +} + +message ChanInfoRequest { + /* + The unique channel ID for the channel. The first 3 bytes are the block + height, the next 3 the index within the block, and the last 2 bytes are the + output index for the channel. + */ + uint64 chan_id = 1 [jstype = JS_STRING]; +} + +message NetworkInfoRequest { +} +message NetworkInfo { + uint32 graph_diameter = 1; + double avg_out_degree = 2; + uint32 max_out_degree = 3; + + uint32 num_nodes = 4; + uint32 num_channels = 5; + + int64 total_network_capacity = 6; + + double avg_channel_size = 7; + int64 min_channel_size = 8; + int64 max_channel_size = 9; + int64 median_channel_size_sat = 10; + + // The number of edges marked as zombies. + uint64 num_zombie_chans = 11; + + // TODO(roasbeef): fee rate info, expiry + // * also additional RPC for tracking fee info once in +} + +message StopRequest { +} +message StopResponse { +} + +message GraphTopologySubscription { +} +message GraphTopologyUpdate { + repeated NodeUpdate node_updates = 1; + repeated ChannelEdgeUpdate channel_updates = 2; + repeated ClosedChannelUpdate closed_chans = 3; +} +message NodeUpdate { + /* + Deprecated, use node_addresses. + */ + repeated string addresses = 1 [deprecated = true]; + + string identity_key = 2; + + /* + Deprecated, use features. + */ + bytes global_features = 3 [deprecated = true]; + + string alias = 4; + string color = 5; + repeated NodeAddress node_addresses = 7; + + /* + Features that the node has advertised in the init message, node + announcements and invoices. + */ + map features = 6; +} +message ChannelEdgeUpdate { + /* + The unique channel ID for the channel. The first 3 bytes are the block + height, the next 3 the index within the block, and the last 2 bytes are the + output index for the channel. + */ + uint64 chan_id = 1 [jstype = JS_STRING]; + + ChannelPoint chan_point = 2; + + int64 capacity = 3; + + RoutingPolicy routing_policy = 4; + + string advertising_node = 5; + string connecting_node = 6; +} +message ClosedChannelUpdate { + /* + The unique channel ID for the channel. The first 3 bytes are the block + height, the next 3 the index within the block, and the last 2 bytes are the + output index for the channel. + */ + uint64 chan_id = 1 [jstype = JS_STRING]; + int64 capacity = 2; + uint32 closed_height = 3; + ChannelPoint chan_point = 4; +} + +message HopHint { + // The public key of the node at the start of the channel. + string node_id = 1; + + // The unique identifier of the channel. + uint64 chan_id = 2 [jstype = JS_STRING]; + + // The base fee of the channel denominated in millisatoshis. + uint32 fee_base_msat = 3; + + /* + The fee rate of the channel for sending one satoshi across it denominated in + millionths of a satoshi. + */ + uint32 fee_proportional_millionths = 4; + + // The time-lock delta of the channel. + uint32 cltv_expiry_delta = 5; +} + +message SetID { + bytes set_id = 1; +} + +message RouteHint { + /* + A list of hop hints that when chained together can assist in reaching a + specific destination. + */ + repeated HopHint hop_hints = 1; +} + +message BlindedPaymentPath { + // The blinded path to send the payment to. + BlindedPath blinded_path = 1; + + // The base fee for the blinded path provided, expressed in msat. + uint64 base_fee_msat = 2; + + // The proportional fee for the blinded path provided, expressed in msat. + uint64 proportional_fee_msat = 3; + + /* + The total CLTV delta for the blinded path provided, including the + final CLTV delta for the receiving node. + */ + uint32 total_cltv_delta = 4; + + /* + The minimum hltc size that may be sent over the blinded path, expressed + in msat. + */ + uint64 htlc_min_msat = 5; + + /* + The maximum htlc size that may be sent over the blinded path, expressed + in msat. + */ + uint64 htlc_max_msat = 6; + + // The feature bits for the route. + repeated FeatureBit features = 7; +} + +message BlindedPath { + // The unblinded pubkey of the introduction node for the route. + bytes introduction_node = 1; + + // The ephemeral pubkey used by nodes in the blinded route. + bytes blinding_point = 2; + + /* + A set of blinded node keys and data blobs for the blinded portion of the + route. Note that the first hop is expected to be the introduction node, + so the route is always expected to have at least one hop. + */ + repeated BlindedHop blinded_hops = 3; +} + +message BlindedHop { + // The blinded public key of the node. + bytes blinded_node = 1; + + // An encrypted blob of data provided to the blinded node. + bytes encrypted_data = 2; +} + +message AMPInvoiceState { + // The state the HTLCs associated with this setID are in. + InvoiceHTLCState state = 1; + + // The settle index of this HTLC set, if the invoice state is settled. + uint64 settle_index = 2; + + // The time this HTLC set was settled expressed in unix epoch. + int64 settle_time = 3; + + // The total amount paid for the sub-invoice expressed in milli satoshis. + int64 amt_paid_msat = 5; +} + +message Invoice { + /* + An optional memo to attach along with the invoice. Used for record keeping + purposes for the invoice's creator, and will also be set in the description + field of the encoded payment request if the description_hash field is not + being used. + */ + string memo = 1; + + reserved 2; + + /* + The hex-encoded preimage (32 byte) which will allow settling an incoming + HTLC payable to this preimage. When using REST, this field must be encoded + as base64. + */ + bytes r_preimage = 3; + + /* + The hash of the preimage. When using REST, this field must be encoded as + base64. + Note: Output only, don't specify for creating an invoice. + */ + bytes r_hash = 4; + + /* + The value of this invoice in satoshis + + The fields value and value_msat are mutually exclusive. + */ + int64 value = 5; + + /* + The value of this invoice in millisatoshis + + The fields value and value_msat are mutually exclusive. + */ + int64 value_msat = 23; + + /* + Whether this invoice has been fulfilled. + + The field is deprecated. Use the state field instead (compare to SETTLED). + */ + bool settled = 6 [deprecated = true]; + + /* + When this invoice was created. + Measured in seconds since the unix epoch. + Note: Output only, don't specify for creating an invoice. + */ + int64 creation_date = 7; + + /* + When this invoice was settled. + Measured in seconds since the unix epoch. + Note: Output only, don't specify for creating an invoice. + */ + int64 settle_date = 8; + + /* + A bare-bones invoice for a payment within the Lightning Network. With the + details of the invoice, the sender has all the data necessary to send a + payment to the recipient. + Note: Output only, don't specify for creating an invoice. + */ + string payment_request = 9; + + /* + Hash (SHA-256) of a description of the payment. Used if the description of + payment (memo) is too long to naturally fit within the description field + of an encoded payment request. When using REST, this field must be encoded + as base64. + */ + bytes description_hash = 10; + + // Payment request expiry time in seconds. Default is 86400 (24 hours). + int64 expiry = 11; + + // Fallback on-chain address. + string fallback_addr = 12; + + // Delta to use for the time-lock of the CLTV extended to the final hop. + uint64 cltv_expiry = 13; + + /* + Route hints that can each be individually used to assist in reaching the + invoice's destination. + */ + repeated RouteHint route_hints = 14; + + // Whether this invoice should include routing hints for private channels. + // Note: When enabled, if value and value_msat are zero, a large number of + // hints with these channels can be included, which might not be desirable. + bool private = 15; + + /* + The "add" index of this invoice. Each newly created invoice will increment + this index making it monotonically increasing. Callers to the + SubscribeInvoices call can use this to instantly get notified of all added + invoices with an add_index greater than this one. + Note: Output only, don't specify for creating an invoice. + */ + uint64 add_index = 16; + + /* + The "settle" index of this invoice. Each newly settled invoice will + increment this index making it monotonically increasing. Callers to the + SubscribeInvoices call can use this to instantly get notified of all + settled invoices with an settle_index greater than this one. + Note: Output only, don't specify for creating an invoice. + */ + uint64 settle_index = 17; + + // Deprecated, use amt_paid_sat or amt_paid_msat. + int64 amt_paid = 18 [deprecated = true]; + + /* + The amount that was accepted for this invoice, in satoshis. This will ONLY + be set if this invoice has been settled or accepted. We provide this field + as if the invoice was created with a zero value, then we need to record what + amount was ultimately accepted. Additionally, it's possible that the sender + paid MORE that was specified in the original invoice. So we'll record that + here as well. + Note: Output only, don't specify for creating an invoice. + */ + int64 amt_paid_sat = 19; + + /* + The amount that was accepted for this invoice, in millisatoshis. This will + ONLY be set if this invoice has been settled or accepted. We provide this + field as if the invoice was created with a zero value, then we need to + record what amount was ultimately accepted. Additionally, it's possible that + the sender paid MORE that was specified in the original invoice. So we'll + record that here as well. + Note: Output only, don't specify for creating an invoice. + */ + int64 amt_paid_msat = 20; + + enum InvoiceState { + OPEN = 0; + SETTLED = 1; + CANCELED = 2; + ACCEPTED = 3; + } + + /* + The state the invoice is in. + Note: Output only, don't specify for creating an invoice. + */ + InvoiceState state = 21; + + /* + List of HTLCs paying to this invoice [EXPERIMENTAL]. + Note: Output only, don't specify for creating an invoice. + */ + repeated InvoiceHTLC htlcs = 22; + + /* + List of features advertised on the invoice. + Note: Output only, don't specify for creating an invoice. + */ + map features = 24; + + /* + Indicates if this invoice was a spontaneous payment that arrived via keysend + [EXPERIMENTAL]. + Note: Output only, don't specify for creating an invoice. + */ + bool is_keysend = 25; + + /* + The payment address of this invoice. This value will be used in MPP + payments, and also for newer invoices that always require the MPP payload + for added end-to-end security. + Note: Output only, don't specify for creating an invoice. + */ + bytes payment_addr = 26; + + /* + Signals whether or not this is an AMP invoice. + */ + bool is_amp = 27; + + /* + [EXPERIMENTAL]: + + Maps a 32-byte hex-encoded set ID to the sub-invoice AMP state for the + given set ID. This field is always populated for AMP invoices, and can be + used along side LookupInvoice to obtain the HTLC information related to a + given sub-invoice. + Note: Output only, don't specify for creating an invoice. + */ + map amp_invoice_state = 28; +} + +enum InvoiceHTLCState { + ACCEPTED = 0; + SETTLED = 1; + CANCELED = 2; +} + +// Details of an HTLC that paid to an invoice +message InvoiceHTLC { + // Short channel id over which the htlc was received. + uint64 chan_id = 1 [jstype = JS_STRING]; + + // Index identifying the htlc on the channel. + uint64 htlc_index = 2; + + // The amount of the htlc in msat. + uint64 amt_msat = 3; + + // Block height at which this htlc was accepted. + int32 accept_height = 4; + + // Time at which this htlc was accepted. + int64 accept_time = 5; + + // Time at which this htlc was settled or canceled. + int64 resolve_time = 6; + + // Block height at which this htlc expires. + int32 expiry_height = 7; + + // Current state the htlc is in. + InvoiceHTLCState state = 8; + + // Custom tlv records. + map custom_records = 9; + + // The total amount of the mpp payment in msat. + uint64 mpp_total_amt_msat = 10; + + // Details relevant to AMP HTLCs, only populated if this is an AMP HTLC. + AMP amp = 11; +} + +// Details specific to AMP HTLCs. +message AMP { + // An n-of-n secret share of the root seed from which child payment hashes + // and preimages are derived. + bytes root_share = 1; + + // An identifier for the HTLC set that this HTLC belongs to. + bytes set_id = 2; + + // A nonce used to randomize the child preimage and child hash from a given + // root_share. + uint32 child_index = 3; + + // The payment hash of the AMP HTLC. + bytes hash = 4; + + // The preimage used to settle this AMP htlc. This field will only be + // populated if the invoice is in InvoiceState_ACCEPTED or + // InvoiceState_SETTLED. + bytes preimage = 5; +} + +message AddInvoiceResponse { + bytes r_hash = 1; + + /* + A bare-bones invoice for a payment within the Lightning Network. With the + details of the invoice, the sender has all the data necessary to send a + payment to the recipient. + */ + string payment_request = 2; + + /* + The "add" index of this invoice. Each newly created invoice will increment + this index making it monotonically increasing. Callers to the + SubscribeInvoices call can use this to instantly get notified of all added + invoices with an add_index greater than this one. + */ + uint64 add_index = 16; + + /* + The payment address of the generated invoice. This value should be used + in all payments for this invoice as we require it for end to end + security. + */ + bytes payment_addr = 17; +} +message PaymentHash { + /* + The hex-encoded payment hash of the invoice to be looked up. The passed + payment hash must be exactly 32 bytes, otherwise an error is returned. + Deprecated now that the REST gateway supports base64 encoding of bytes + fields. + */ + string r_hash_str = 1 [deprecated = true]; + + /* + The payment hash of the invoice to be looked up. When using REST, this field + must be encoded as base64. + */ + bytes r_hash = 2; +} + +message ListInvoiceRequest { + /* + If set, only invoices that are not settled and not canceled will be returned + in the response. + */ + bool pending_only = 1; + + /* + The index of an invoice that will be used as either the start or end of a + query to determine which invoices should be returned in the response. + */ + uint64 index_offset = 4; + + // The max number of invoices to return in the response to this query. + uint64 num_max_invoices = 5; + + /* + If set, the invoices returned will result from seeking backwards from the + specified index offset. This can be used to paginate backwards. + */ + bool reversed = 6; + + // If set, returns all invoices with a creation date greater than or equal + // to it. Measured in seconds since the unix epoch. + uint64 creation_date_start = 7; + + // If set, returns all invoices with a creation date less than or equal to + // it. Measured in seconds since the unix epoch. + uint64 creation_date_end = 8; +} + +message ListInvoiceResponse { + /* + A list of invoices from the time slice of the time series specified in the + request. + */ + repeated Invoice invoices = 1; + + /* + The index of the last item in the set of returned invoices. This can be used + to seek further, pagination style. + */ + uint64 last_index_offset = 2; + + /* + The index of the last item in the set of returned invoices. This can be used + to seek backwards, pagination style. + */ + uint64 first_index_offset = 3; +} + +message InvoiceSubscription { + /* + If specified (non-zero), then we'll first start by sending out + notifications for all added indexes with an add_index greater than this + value. This allows callers to catch up on any events they missed while they + weren't connected to the streaming RPC. + */ + uint64 add_index = 1; + + /* + If specified (non-zero), then we'll first start by sending out + notifications for all settled indexes with an settle_index greater than + this value. This allows callers to catch up on any events they missed while + they weren't connected to the streaming RPC. + */ + uint64 settle_index = 2; +} + +enum PaymentFailureReason { + /* + Payment isn't failed (yet). + */ + FAILURE_REASON_NONE = 0; + + /* + There are more routes to try, but the payment timeout was exceeded. + */ + FAILURE_REASON_TIMEOUT = 1; + + /* + All possible routes were tried and failed permanently. Or were no + routes to the destination at all. + */ + FAILURE_REASON_NO_ROUTE = 2; + + /* + A non-recoverable error has occured. + */ + FAILURE_REASON_ERROR = 3; + + /* + Payment details incorrect (unknown hash, invalid amt or + invalid final cltv delta) + */ + FAILURE_REASON_INCORRECT_PAYMENT_DETAILS = 4; + + /* + Insufficient local balance. + */ + FAILURE_REASON_INSUFFICIENT_BALANCE = 5; +} + +message Payment { + // The payment hash + string payment_hash = 1; + + // Deprecated, use value_sat or value_msat. + int64 value = 2 [deprecated = true]; + + // Deprecated, use creation_time_ns + int64 creation_date = 3 [deprecated = true]; + + reserved 4; + + // Deprecated, use fee_sat or fee_msat. + int64 fee = 5 [deprecated = true]; + + // The payment preimage + string payment_preimage = 6; + + // The value of the payment in satoshis + int64 value_sat = 7; + + // The value of the payment in milli-satoshis + int64 value_msat = 8; + + // The optional payment request being fulfilled. + string payment_request = 9; + + enum PaymentStatus { + // Deprecated. This status will never be returned. + UNKNOWN = 0 [deprecated = true]; + + // Payment has inflight HTLCs. + IN_FLIGHT = 1; + + // Payment is settled. + SUCCEEDED = 2; + + // Payment is failed. + FAILED = 3; + + // Payment is created and has not attempted any HTLCs. + INITIATED = 4; + } + + // The status of the payment. + PaymentStatus status = 10; + + // The fee paid for this payment in satoshis + int64 fee_sat = 11; + + // The fee paid for this payment in milli-satoshis + int64 fee_msat = 12; + + // The time in UNIX nanoseconds at which the payment was created. + int64 creation_time_ns = 13; + + // The HTLCs made in attempt to settle the payment. + repeated HTLCAttempt htlcs = 14; + + /* + The creation index of this payment. Each payment can be uniquely identified + by this index, which may not strictly increment by 1 for payments made in + older versions of lnd. + */ + uint64 payment_index = 15; + + PaymentFailureReason failure_reason = 16; +} + +message HTLCAttempt { + // The unique ID that is used for this attempt. + uint64 attempt_id = 7; + + enum HTLCStatus { + IN_FLIGHT = 0; + SUCCEEDED = 1; + FAILED = 2; + } + + // The status of the HTLC. + HTLCStatus status = 1; + + // The route taken by this HTLC. + Route route = 2; + + // The time in UNIX nanoseconds at which this HTLC was sent. + int64 attempt_time_ns = 3; + + /* + The time in UNIX nanoseconds at which this HTLC was settled or failed. + This value will not be set if the HTLC is still IN_FLIGHT. + */ + int64 resolve_time_ns = 4; + + // Detailed htlc failure info. + Failure failure = 5; + + // The preimage that was used to settle the HTLC. + bytes preimage = 6; +} + +message ListPaymentsRequest { + /* + If true, then return payments that have not yet fully completed. This means + that pending payments, as well as failed payments will show up if this + field is set to true. This flag doesn't change the meaning of the indices, + which are tied to individual payments. + */ + bool include_incomplete = 1; + + /* + The index of a payment that will be used as either the start or end of a + query to determine which payments should be returned in the response. The + index_offset is exclusive. In the case of a zero index_offset, the query + will start with the oldest payment when paginating forwards, or will end + with the most recent payment when paginating backwards. + */ + uint64 index_offset = 2; + + // The maximal number of payments returned in the response to this query. + uint64 max_payments = 3; + + /* + If set, the payments returned will result from seeking backwards from the + specified index offset. This can be used to paginate backwards. The order + of the returned payments is always oldest first (ascending index order). + */ + bool reversed = 4; + + /* + If set, all payments (complete and incomplete, independent of the + max_payments parameter) will be counted. Note that setting this to true will + increase the run time of the call significantly on systems that have a lot + of payments, as all of them have to be iterated through to be counted. + */ + bool count_total_payments = 5; + + // If set, returns all invoices with a creation date greater than or equal + // to it. Measured in seconds since the unix epoch. + uint64 creation_date_start = 6; + + // If set, returns all invoices with a creation date less than or equal to + // it. Measured in seconds since the unix epoch. + uint64 creation_date_end = 7; +} + +message ListPaymentsResponse { + // The list of payments + repeated Payment payments = 1; + + /* + The index of the first item in the set of returned payments. This can be + used as the index_offset to continue seeking backwards in the next request. + */ + uint64 first_index_offset = 2; + + /* + The index of the last item in the set of returned payments. This can be used + as the index_offset to continue seeking forwards in the next request. + */ + uint64 last_index_offset = 3; + + /* + Will only be set if count_total_payments in the request was set. Represents + the total number of payments (complete and incomplete, independent of the + number of payments requested in the query) currently present in the payments + database. + */ + uint64 total_num_payments = 4; +} + +message DeletePaymentRequest { + // Payment hash to delete. + bytes payment_hash = 1; + + /* + Only delete failed HTLCs from the payment, not the payment itself. + */ + bool failed_htlcs_only = 2; +} + +message DeleteAllPaymentsRequest { + // Only delete failed payments. + bool failed_payments_only = 1; + + /* + Only delete failed HTLCs from payments, not the payment itself. + */ + bool failed_htlcs_only = 2; +} + +message DeletePaymentResponse { +} + +message DeleteAllPaymentsResponse { +} + +message AbandonChannelRequest { + ChannelPoint channel_point = 1; + + bool pending_funding_shim_only = 2; + + /* + Override the requirement for being in dev mode by setting this to true and + confirming the user knows what they are doing and this is a potential foot + gun to lose funds if used on active channels. + */ + bool i_know_what_i_am_doing = 3; +} + +message AbandonChannelResponse { +} + +message DebugLevelRequest { + bool show = 1; + string level_spec = 2; +} +message DebugLevelResponse { + string sub_systems = 1; +} + +message PayReqString { + // The payment request string to be decoded + string pay_req = 1; +} +message PayReq { + string destination = 1; + string payment_hash = 2; + int64 num_satoshis = 3; + int64 timestamp = 4; + int64 expiry = 5; + string description = 6; + string description_hash = 7; + string fallback_addr = 8; + int64 cltv_expiry = 9; + repeated RouteHint route_hints = 10; + bytes payment_addr = 11; + int64 num_msat = 12; + map features = 13; +} + +enum FeatureBit { + DATALOSS_PROTECT_REQ = 0; + DATALOSS_PROTECT_OPT = 1; + INITIAL_ROUING_SYNC = 3; + UPFRONT_SHUTDOWN_SCRIPT_REQ = 4; + UPFRONT_SHUTDOWN_SCRIPT_OPT = 5; + GOSSIP_QUERIES_REQ = 6; + GOSSIP_QUERIES_OPT = 7; + TLV_ONION_REQ = 8; + TLV_ONION_OPT = 9; + EXT_GOSSIP_QUERIES_REQ = 10; + EXT_GOSSIP_QUERIES_OPT = 11; + STATIC_REMOTE_KEY_REQ = 12; + STATIC_REMOTE_KEY_OPT = 13; + PAYMENT_ADDR_REQ = 14; + PAYMENT_ADDR_OPT = 15; + MPP_REQ = 16; + MPP_OPT = 17; + WUMBO_CHANNELS_REQ = 18; + WUMBO_CHANNELS_OPT = 19; + ANCHORS_REQ = 20; + ANCHORS_OPT = 21; + ANCHORS_ZERO_FEE_HTLC_REQ = 22; + ANCHORS_ZERO_FEE_HTLC_OPT = 23; + AMP_REQ = 30; + AMP_OPT = 31; +} + +message Feature { + string name = 2; + bool is_required = 3; + bool is_known = 4; +} + +message FeeReportRequest { +} +message ChannelFeeReport { + // The short channel id that this fee report belongs to. + uint64 chan_id = 5 [jstype = JS_STRING]; + + // The channel that this fee report belongs to. + string channel_point = 1; + + // The base fee charged regardless of the number of milli-satoshis sent. + int64 base_fee_msat = 2; + + // The amount charged per milli-satoshis transferred expressed in + // millionths of a satoshi. + int64 fee_per_mil = 3; + + // The effective fee rate in milli-satoshis. Computed by dividing the + // fee_per_mil value by 1 million. + double fee_rate = 4; +} +message FeeReportResponse { + // An array of channel fee reports which describes the current fee schedule + // for each channel. + repeated ChannelFeeReport channel_fees = 1; + + // The total amount of fee revenue (in satoshis) the switch has collected + // over the past 24 hrs. + uint64 day_fee_sum = 2; + + // The total amount of fee revenue (in satoshis) the switch has collected + // over the past 1 week. + uint64 week_fee_sum = 3; + + // The total amount of fee revenue (in satoshis) the switch has collected + // over the past 1 month. + uint64 month_fee_sum = 4; +} + +message PolicyUpdateRequest { + oneof scope { + // If set, then this update applies to all currently active channels. + bool global = 1; + + // If set, this update will target a specific channel. + ChannelPoint chan_point = 2; + } + + // The base fee charged regardless of the number of milli-satoshis sent. + int64 base_fee_msat = 3; + + // The effective fee rate in milli-satoshis. The precision of this value + // goes up to 6 decimal places, so 1e-6. + double fee_rate = 4; + + // The effective fee rate in micro-satoshis (parts per million). + uint32 fee_rate_ppm = 9; + + // The required timelock delta for HTLCs forwarded over the channel. + uint32 time_lock_delta = 5; + + // If set, the maximum HTLC size in milli-satoshis. If unset, the maximum + // HTLC will be unchanged. + uint64 max_htlc_msat = 6; + + // The minimum HTLC size in milli-satoshis. Only applied if + // min_htlc_msat_specified is true. + uint64 min_htlc_msat = 7; + + // If true, min_htlc_msat is applied. + bool min_htlc_msat_specified = 8; +} +enum UpdateFailure { + UPDATE_FAILURE_UNKNOWN = 0; + UPDATE_FAILURE_PENDING = 1; + UPDATE_FAILURE_NOT_FOUND = 2; + UPDATE_FAILURE_INTERNAL_ERR = 3; + UPDATE_FAILURE_INVALID_PARAMETER = 4; +} + +message FailedUpdate { + // The outpoint in format txid:n + OutPoint outpoint = 1; + + // Reason for the policy update failure. + UpdateFailure reason = 2; + + // A string representation of the policy update error. + string update_error = 3; +} + +message PolicyUpdateResponse { + // List of failed policy updates. + repeated FailedUpdate failed_updates = 1; +} + +message ForwardingHistoryRequest { + // Start time is the starting point of the forwarding history request. All + // records beyond this point will be included, respecting the end time, and + // the index offset. + uint64 start_time = 1; + + // End time is the end point of the forwarding history request. The + // response will carry at most 50k records between the start time and the + // end time. The index offset can be used to implement pagination. + uint64 end_time = 2; + + // Index offset is the offset in the time series to start at. As each + // response can only contain 50k records, callers can use this to skip + // around within a packed time series. + uint32 index_offset = 3; + + // The max number of events to return in the response to this query. + uint32 num_max_events = 4; + + // Informs the server if the peer alias should be looked up for each + // forwarding event. + bool peer_alias_lookup = 5; +} +message ForwardingEvent { + // Timestamp is the time (unix epoch offset) that this circuit was + // completed. Deprecated by timestamp_ns. + uint64 timestamp = 1 [deprecated = true]; + + // The incoming channel ID that carried the HTLC that created the circuit. + uint64 chan_id_in = 2 [jstype = JS_STRING]; + + // The outgoing channel ID that carried the preimage that completed the + // circuit. + uint64 chan_id_out = 4 [jstype = JS_STRING]; + + // The total amount (in satoshis) of the incoming HTLC that created half + // the circuit. + uint64 amt_in = 5; + + // The total amount (in satoshis) of the outgoing HTLC that created the + // second half of the circuit. + uint64 amt_out = 6; + + // The total fee (in satoshis) that this payment circuit carried. + uint64 fee = 7; + + // The total fee (in milli-satoshis) that this payment circuit carried. + uint64 fee_msat = 8; + + // The total amount (in milli-satoshis) of the incoming HTLC that created + // half the circuit. + uint64 amt_in_msat = 9; + + // The total amount (in milli-satoshis) of the outgoing HTLC that created + // the second half of the circuit. + uint64 amt_out_msat = 10; + + // The number of nanoseconds elapsed since January 1, 1970 UTC when this + // circuit was completed. + uint64 timestamp_ns = 11; + + // The peer alias of the incoming channel. + string peer_alias_in = 12; + + // The peer alias of the outgoing channel. + string peer_alias_out = 13; + + // TODO(roasbeef): add settlement latency? + // * use FPE on the chan id? + // * also list failures? +} +message ForwardingHistoryResponse { + // A list of forwarding events from the time slice of the time series + // specified in the request. + repeated ForwardingEvent forwarding_events = 1; + + // The index of the last time in the set of returned forwarding events. Can + // be used to seek further, pagination style. + uint32 last_offset_index = 2; +} + +message ExportChannelBackupRequest { + // The target channel point to obtain a back up for. + ChannelPoint chan_point = 1; +} + +message ChannelBackup { + /* + Identifies the channel that this backup belongs to. + */ + ChannelPoint chan_point = 1; + + /* + Is an encrypted single-chan backup. this can be passed to + RestoreChannelBackups, or the WalletUnlocker Init and Unlock methods in + order to trigger the recovery protocol. When using REST, this field must be + encoded as base64. + */ + bytes chan_backup = 2; +} + +message MultiChanBackup { + /* + Is the set of all channels that are included in this multi-channel backup. + */ + repeated ChannelPoint chan_points = 1; + + /* + A single encrypted blob containing all the static channel backups of the + channel listed above. This can be stored as a single file or blob, and + safely be replaced with any prior/future versions. When using REST, this + field must be encoded as base64. + */ + bytes multi_chan_backup = 2; +} + +message ChanBackupExportRequest { +} +message ChanBackupSnapshot { + /* + The set of new channels that have been added since the last channel backup + snapshot was requested. + */ + ChannelBackups single_chan_backups = 1; + + /* + A multi-channel backup that covers all open channels currently known to + lnd. + */ + MultiChanBackup multi_chan_backup = 2; +} + +message ChannelBackups { + /* + A set of single-chan static channel backups. + */ + repeated ChannelBackup chan_backups = 1; +} + +message RestoreChanBackupRequest { + oneof backup { + /* + The channels to restore as a list of channel/backup pairs. + */ + ChannelBackups chan_backups = 1; + + /* + The channels to restore in the packed multi backup format. When using + REST, this field must be encoded as base64. + */ + bytes multi_chan_backup = 2; + } +} +message RestoreBackupResponse { +} + +message ChannelBackupSubscription { +} + +message VerifyChanBackupResponse { +} + +message MacaroonPermission { + // The entity a permission grants access to. + string entity = 1; + + // The action that is granted. + string action = 2; +} +message BakeMacaroonRequest { + // The list of permissions the new macaroon should grant. + repeated MacaroonPermission permissions = 1; + + // The root key ID used to create the macaroon, must be a positive integer. + uint64 root_key_id = 2; + + /* + Informs the RPC on whether to allow external permissions that LND is not + aware of. + */ + bool allow_external_permissions = 3; +} +message BakeMacaroonResponse { + // The hex encoded macaroon, serialized in binary format. + string macaroon = 1; +} + +message ListMacaroonIDsRequest { +} +message ListMacaroonIDsResponse { + // The list of root key IDs that are in use. + repeated uint64 root_key_ids = 1; +} + +message DeleteMacaroonIDRequest { + // The root key ID to be removed. + uint64 root_key_id = 1; +} +message DeleteMacaroonIDResponse { + // A boolean indicates that the deletion is successful. + bool deleted = 1; +} + +message MacaroonPermissionList { + // A list of macaroon permissions. + repeated MacaroonPermission permissions = 1; +} + +message ListPermissionsRequest { +} +message ListPermissionsResponse { + /* + A map between all RPC method URIs and their required macaroon permissions to + access them. + */ + map method_permissions = 1; +} + +message Failure { + enum FailureCode { + /* + The numbers assigned in this enumeration match the failure codes as + defined in BOLT #4. Because protobuf 3 requires enums to start with 0, + a RESERVED value is added. + */ + RESERVED = 0; + + INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS = 1; + INCORRECT_PAYMENT_AMOUNT = 2; + FINAL_INCORRECT_CLTV_EXPIRY = 3; + FINAL_INCORRECT_HTLC_AMOUNT = 4; + FINAL_EXPIRY_TOO_SOON = 5; + INVALID_REALM = 6; + EXPIRY_TOO_SOON = 7; + INVALID_ONION_VERSION = 8; + INVALID_ONION_HMAC = 9; + INVALID_ONION_KEY = 10; + AMOUNT_BELOW_MINIMUM = 11; + FEE_INSUFFICIENT = 12; + INCORRECT_CLTV_EXPIRY = 13; + CHANNEL_DISABLED = 14; + TEMPORARY_CHANNEL_FAILURE = 15; + REQUIRED_NODE_FEATURE_MISSING = 16; + REQUIRED_CHANNEL_FEATURE_MISSING = 17; + UNKNOWN_NEXT_PEER = 18; + TEMPORARY_NODE_FAILURE = 19; + PERMANENT_NODE_FAILURE = 20; + PERMANENT_CHANNEL_FAILURE = 21; + EXPIRY_TOO_FAR = 22; + MPP_TIMEOUT = 23; + INVALID_ONION_PAYLOAD = 24; + + /* + An internal error occurred. + */ + INTERNAL_FAILURE = 997; + + /* + The error source is known, but the failure itself couldn't be decoded. + */ + UNKNOWN_FAILURE = 998; + + /* + An unreadable failure result is returned if the received failure message + cannot be decrypted. In that case the error source is unknown. + */ + UNREADABLE_FAILURE = 999; + } + + // Failure code as defined in the Lightning spec + FailureCode code = 1; + + reserved 2; + + // An optional channel update message. + ChannelUpdate channel_update = 3; + + // A failure type-dependent htlc value. + uint64 htlc_msat = 4; + + // The sha256 sum of the onion payload. + bytes onion_sha_256 = 5; + + // A failure type-dependent cltv expiry value. + uint32 cltv_expiry = 6; + + // A failure type-dependent flags value. + uint32 flags = 7; + + /* + The position in the path of the intermediate or final node that generated + the failure message. Position zero is the sender node. + **/ + uint32 failure_source_index = 8; + + // A failure type-dependent block height. + uint32 height = 9; +} + +message ChannelUpdate { + /* + The signature that validates the announced data and proves the ownership + of node id. + */ + bytes signature = 1; + + /* + The target chain that this channel was opened within. This value + should be the genesis hash of the target chain. Along with the short + channel ID, this uniquely identifies the channel globally in a + blockchain. + */ + bytes chain_hash = 2; + + /* + The unique description of the funding transaction. + */ + uint64 chan_id = 3 [jstype = JS_STRING]; + + /* + A timestamp that allows ordering in the case of multiple announcements. + We should ignore the message if timestamp is not greater than the + last-received. + */ + uint32 timestamp = 4; + + /* + The bitfield that describes whether optional fields are present in this + update. Currently, the least-significant bit must be set to 1 if the + optional field MaxHtlc is present. + */ + uint32 message_flags = 10; + + /* + The bitfield that describes additional meta-data concerning how the + update is to be interpreted. Currently, the least-significant bit must be + set to 0 if the creating node corresponds to the first node in the + previously sent channel announcement and 1 otherwise. If the second bit + is set, then the channel is set to be disabled. + */ + uint32 channel_flags = 5; + + /* + The minimum number of blocks this node requires to be added to the expiry + of HTLCs. This is a security parameter determined by the node operator. + This value represents the required gap between the time locks of the + incoming and outgoing HTLC's set to this node. + */ + uint32 time_lock_delta = 6; + + /* + The minimum HTLC value which will be accepted. + */ + uint64 htlc_minimum_msat = 7; + + /* + The base fee that must be used for incoming HTLC's to this particular + channel. This value will be tacked onto the required for a payment + independent of the size of the payment. + */ + uint32 base_fee = 8; + + /* + The fee rate that will be charged per millionth of a satoshi. + */ + uint32 fee_rate = 9; + + /* + The maximum HTLC value which will be accepted. + */ + uint64 htlc_maximum_msat = 11; + + /* + The set of data that was appended to this message, some of which we may + not actually know how to iterate or parse. By holding onto this data, we + ensure that we're able to properly validate the set of signatures that + cover these new fields, and ensure we're able to make upgrades to the + network in a forwards compatible manner. + */ + bytes extra_opaque_data = 12; +} + +message MacaroonId { + bytes nonce = 1; + bytes storageId = 2; + repeated Op ops = 3; +} + +message Op { + string entity = 1; + repeated string actions = 2; +} + +message CheckMacPermRequest { + bytes macaroon = 1; + repeated MacaroonPermission permissions = 2; + string fullMethod = 3; +} + +message CheckMacPermResponse { + bool valid = 1; +} + +message RPCMiddlewareRequest { + /* + The unique ID of the intercepted original gRPC request. Useful for mapping + request to response when implementing full duplex message interception. For + streaming requests, this will be the same ID for all incoming and outgoing + middleware intercept messages of the _same_ stream. + */ + uint64 request_id = 1; + + /* + The raw bytes of the complete macaroon as sent by the gRPC client in the + original request. This might be empty for a request that doesn't require + macaroons such as the wallet unlocker RPCs. + */ + bytes raw_macaroon = 2; + + /* + The parsed condition of the macaroon's custom caveat for convenient access. + This field only contains the value of the custom caveat that the handling + middleware has registered itself for. The condition _must_ be validated for + messages of intercept_type stream_auth and request! + */ + string custom_caveat_condition = 3; + + /* + There are three types of messages that will be sent to the middleware for + inspection and approval: Stream authentication, request and response + interception. The first two can only be accepted (=forward to main RPC + server) or denied (=return error to client). Intercepted responses can also + be replaced/overwritten. + */ + oneof intercept_type { + /* + Intercept stream authentication: each new streaming RPC call that is + initiated against lnd and contains the middleware's custom macaroon + caveat can be approved or denied based upon the macaroon in the stream + header. This message will only be sent for streaming RPCs, unary RPCs + must handle the macaroon authentication in the request interception to + avoid an additional message round trip between lnd and the middleware. + */ + StreamAuth stream_auth = 4; + + /* + Intercept incoming gRPC client request message: all incoming messages, + both on streaming and unary RPCs, are forwarded to the middleware for + inspection. For unary RPC messages the middleware is also expected to + validate the custom macaroon caveat of the request. + */ + RPCMessage request = 5; + + /* + Intercept outgoing gRPC response message: all outgoing messages, both on + streaming and unary RPCs, are forwarded to the middleware for inspection + and amendment. The response in this message is the original response as + it was generated by the main RPC server. It can either be accepted + (=forwarded to the client), replaced/overwritten with a new message of + the same type, or replaced by an error message. + */ + RPCMessage response = 6; + + /* + This is used to indicate to the client that the server has successfully + registered the interceptor. This is only used in the very first message + that the server sends to the client after the client sends the server + the middleware registration message. + */ + bool reg_complete = 8; + } + + /* + The unique message ID of this middleware intercept message. There can be + multiple middleware intercept messages per single gRPC request (one for the + incoming request and one for the outgoing response) or gRPC stream (one for + each incoming message and one for each outgoing response). This message ID + must be referenced when responding (accepting/rejecting/modifying) to an + intercept message. + */ + uint64 msg_id = 7; +} + +message StreamAuth { + /* + The full URI (in the format /./MethodName, for + example /lnrpc.Lightning/GetInfo) of the streaming RPC method that was just + established. + */ + string method_full_uri = 1; +} + +message RPCMessage { + /* + The full URI (in the format /./MethodName, for + example /lnrpc.Lightning/GetInfo) of the RPC method the message was sent + to/from. + */ + string method_full_uri = 1; + + /* + Indicates whether the message was sent over a streaming RPC method or not. + */ + bool stream_rpc = 2; + + /* + The full canonical gRPC name of the message type (in the format + .TypeName, for example lnrpc.GetInfoRequest). In case of an + error being returned from lnd, this simply contains the string "error". + */ + string type_name = 3; + + /* + The full content of the gRPC message, serialized in the binary protobuf + format. + */ + bytes serialized = 4; + + /* + Indicates that the response from lnd was an error, not a gRPC response. If + this is set to true then the type_name contains the string "error" and + serialized contains the error string. + */ + bool is_error = 5; +} + +message RPCMiddlewareResponse { + /* + The request message ID this response refers to. Must always be set when + giving feedback to an intercept but is ignored for the initial registration + message. + */ + uint64 ref_msg_id = 1; + + /* + The middleware can only send two types of messages to lnd: The initial + registration message that identifies the middleware and after that only + feedback messages to requests sent to the middleware. + */ + oneof middleware_message { + /* + The registration message identifies the middleware that's being + registered in lnd. The registration message must be sent immediately + after initiating the RegisterRpcMiddleware stream, otherwise lnd will + time out the attempt and terminate the request. NOTE: The middleware + will only receive interception messages for requests that contain a + macaroon with the custom caveat that the middleware declares it is + responsible for handling in the registration message! As a security + measure, _no_ middleware can intercept requests made with _unencumbered_ + macaroons! + */ + MiddlewareRegistration register = 2; + + /* + The middleware received an interception request and gives feedback to + it. The request_id indicates what message the feedback refers to. + */ + InterceptFeedback feedback = 3; + } +} + +message MiddlewareRegistration { + /* + The name of the middleware to register. The name should be as informative + as possible and is logged on registration. + */ + string middleware_name = 1; + + /* + The name of the custom macaroon caveat that this middleware is responsible + for. Only requests/responses that contain a macaroon with the registered + custom caveat are forwarded for interception to the middleware. The + exception being the read-only mode: All requests/responses are forwarded to + a middleware that requests read-only access but such a middleware won't be + allowed to _alter_ responses. As a security measure, _no_ middleware can + change responses to requests made with _unencumbered_ macaroons! + NOTE: Cannot be used at the same time as read_only_mode. + */ + string custom_macaroon_caveat_name = 2; + + /* + Instead of defining a custom macaroon caveat name a middleware can register + itself for read-only access only. In that mode all requests/responses are + forwarded to the middleware but the middleware isn't allowed to alter any of + the responses. + NOTE: Cannot be used at the same time as custom_macaroon_caveat_name. + */ + bool read_only_mode = 3; +} + +message InterceptFeedback { + /* + The error to return to the user. If this is non-empty, the incoming gRPC + stream/request is aborted and the error is returned to the gRPC client. If + this value is empty, it means the middleware accepts the stream/request/ + response and the processing of it can continue. + */ + string error = 1; + + /* + A boolean indicating that the gRPC message should be replaced/overwritten. + This boolean is needed because in protobuf an empty message is serialized as + a 0-length or nil byte slice and we wouldn't be able to distinguish between + an empty replacement message and the "don't replace anything" case. + */ + bool replace_response = 2; + + /* + If the replace_response field is set to true, this field must contain the + binary serialized gRPC message in the protobuf format. + */ + bytes replacement_serialized = 3; +} diff --git a/proto/neutrinorpc/neutrino.proto b/proto/neutrinorpc/neutrino.proto new file mode 100644 index 000000000..5a61feaad --- /dev/null +++ b/proto/neutrinorpc/neutrino.proto @@ -0,0 +1,228 @@ +syntax = "proto3"; + +package neutrinorpc; + +option go_package = "github.com/lightningnetwork/lnd/lnrpc/neutrinorpc"; + +// NeutrinoKit is a service that can be used to get information about the +// current state of the neutrino instance, fetch blocks and add/remove peers. +service NeutrinoKit { + /* + Status returns the status of the light client neutrino instance, + along with height and hash of the best block, and a list of connected + peers. + */ + rpc Status (StatusRequest) returns (StatusResponse); + + /* + AddPeer adds a new peer that has already been connected to the server. + */ + rpc AddPeer (AddPeerRequest) returns (AddPeerResponse); + + /* + DisconnectPeer disconnects a peer by target address. Both outbound and + inbound nodes will be searched for the target node. An error message will + be returned if the peer was not found. + */ + rpc DisconnectPeer (DisconnectPeerRequest) returns (DisconnectPeerResponse); + + /* + IsBanned returns true if the peer is banned, otherwise false. + */ + rpc IsBanned (IsBannedRequest) returns (IsBannedResponse); + + /* + GetBlockHeader returns a block header with a particular block hash. + */ + rpc GetBlockHeader (GetBlockHeaderRequest) returns (GetBlockHeaderResponse); + + /* + GetBlock returns a block with a particular block hash. + */ + rpc GetBlock (GetBlockRequest) returns (GetBlockResponse); + + /* + GetCFilter returns a compact filter from a block. + */ + rpc GetCFilter (GetCFilterRequest) returns (GetCFilterResponse); + + /* + Deprecated, use chainrpc.GetBlockHash instead. + GetBlockHash returns the header hash of a block at a given height. + */ + rpc GetBlockHash (GetBlockHashRequest) returns (GetBlockHashResponse) { + option deprecated = true; + } +} + +message StatusRequest { +} + +message StatusResponse { + // Indicates whether the neutrino backend is active or not. + bool active = 1; + + // Is fully synced. + bool synced = 2; + + // Best block height. + int32 block_height = 3; + + // Best block hash. + string block_hash = 4; + + // Connected peers. + repeated string peers = 5; +} + +message AddPeerRequest { + // Peer to add. + string peer_addrs = 1; +} + +message AddPeerResponse { +} + +message DisconnectPeerRequest { + // Peer to disconnect. + string peer_addrs = 1; +} + +message DisconnectPeerResponse { +} + +message IsBannedRequest { + // Peer to lookup. + string peer_addrs = 1; +} + +message IsBannedResponse { + bool banned = 1; +} + +message GetBlockHeaderRequest { + // Block hash in hex notation. + string hash = 1; +} + +message GetBlockHeaderResponse { + // The block hash (same as provided). + string hash = 1; + + // The number of confirmations. + int64 confirmations = 2; + + // The block size excluding witness data. + int64 stripped_size = 3; + + // The block size (bytes). + int64 size = 4; + + // The block weight as defined in BIP 141. + int64 weight = 5; + + // The block height or index. + int32 height = 6; + + // The block version. + int32 version = 7; + + // The block version. + string version_hex = 8; + + // The merkle root. + string merkleroot = 9; + + // The block time in seconds since epoch (Jan 1 1970 GMT). + int64 time = 10; + + // The nonce. + uint32 nonce = 11; + + // The bits in hex notation. + string bits = 12; + + // The number of transactions in the block. + int32 ntx = 13; + + // The hash of the previous block. + string previous_block_hash = 14; + + // The raw hex of the block. + bytes raw_hex = 15; +} + +message GetBlockRequest { + // Block hash in hex notation. + string hash = 1; +} + +message GetBlockResponse { + // The block hash (same as provided). + string hash = 1; + + // The number of confirmations. + int64 confirmations = 2; + + // The block size excluding witness data. + int64 stripped_size = 3; + + // The block size (bytes). + int64 size = 4; + + // The block weight as defined in BIP 141. + int64 weight = 5; + + // The block height or index. + int32 height = 6; + + // The block version. + int32 version = 7; + + // The block version. + string version_hex = 8; + + // The merkle root. + string merkleroot = 9; + + // List of transaction ids. + repeated string tx = 10; + + // The block time in seconds since epoch (Jan 1 1970 GMT). + int64 time = 11; + + // The nonce. + uint32 nonce = 12; + + // The bits in hex notation. + string bits = 13; + + // The number of transactions in the block. + int32 ntx = 14; + + // The hash of the previous block. + string previous_block_hash = 15; + + // The raw hex of the block. + bytes raw_hex = 16; +} + +message GetCFilterRequest { + // Block hash in hex notation. + string hash = 1; +} + +message GetCFilterResponse { + // GCS filter. + bytes filter = 1; +} + +message GetBlockHashRequest { + // The block height or index. + int32 height = 1; +} + +message GetBlockHashResponse { + // The block hash. + string hash = 1; +} diff --git a/proto/routerrpc/router.proto b/proto/routerrpc/router.proto new file mode 100644 index 000000000..d591cc485 --- /dev/null +++ b/proto/routerrpc/router.proto @@ -0,0 +1,952 @@ +syntax = "proto3"; + +import "lightning.proto"; + +package routerrpc; + +option go_package = "github.com/lightningnetwork/lnd/lnrpc/routerrpc"; + +// Router is a service that offers advanced interaction with the router +// subsystem of the daemon. +service Router { + /* + SendPaymentV2 attempts to route a payment described by the passed + PaymentRequest to the final destination. The call returns a stream of + payment updates. + */ + rpc SendPaymentV2 (SendPaymentRequest) returns (stream lnrpc.Payment); + + /* + TrackPaymentV2 returns an update stream for the payment identified by the + payment hash. + */ + rpc TrackPaymentV2 (TrackPaymentRequest) returns (stream lnrpc.Payment); + + /* + TrackPayments returns an update stream for every payment that is not in a + terminal state. Note that if payments are in-flight while starting a new + subscription, the start of the payment stream could produce out-of-order + and/or duplicate events. In order to get updates for every in-flight + payment attempt make sure to subscribe to this method before initiating any + payments. + */ + rpc TrackPayments (TrackPaymentsRequest) returns (stream lnrpc.Payment); + + /* + EstimateRouteFee allows callers to obtain a lower bound w.r.t how much it + may cost to send an HTLC to the target end destination. + */ + rpc EstimateRouteFee (RouteFeeRequest) returns (RouteFeeResponse); + + /* + Deprecated, use SendToRouteV2. SendToRoute attempts to make a payment via + the specified route. This method differs from SendPayment in that it + allows users to specify a full route manually. This can be used for + things like rebalancing, and atomic swaps. It differs from the newer + SendToRouteV2 in that it doesn't return the full HTLC information. + */ + rpc SendToRoute (SendToRouteRequest) returns (SendToRouteResponse) { + option deprecated = true; + } + + /* + SendToRouteV2 attempts to make a payment via the specified route. This + method differs from SendPayment in that it allows users to specify a full + route manually. This can be used for things like rebalancing, and atomic + swaps. + */ + rpc SendToRouteV2 (SendToRouteRequest) returns (lnrpc.HTLCAttempt); + + /* + ResetMissionControl clears all mission control state and starts with a clean + slate. + */ + rpc ResetMissionControl (ResetMissionControlRequest) + returns (ResetMissionControlResponse); + + /* + QueryMissionControl exposes the internal mission control state to callers. + It is a development feature. + */ + rpc QueryMissionControl (QueryMissionControlRequest) + returns (QueryMissionControlResponse); + + /* + XImportMissionControl is an experimental API that imports the state provided + to the internal mission control's state, using all results which are more + recent than our existing values. These values will only be imported + in-memory, and will not be persisted across restarts. + */ + rpc XImportMissionControl (XImportMissionControlRequest) + returns (XImportMissionControlResponse); + + /* + GetMissionControlConfig returns mission control's current config. + */ + rpc GetMissionControlConfig (GetMissionControlConfigRequest) + returns (GetMissionControlConfigResponse); + + /* + SetMissionControlConfig will set mission control's config, if the config + provided is valid. + */ + rpc SetMissionControlConfig (SetMissionControlConfigRequest) + returns (SetMissionControlConfigResponse); + + /* + Deprecated. QueryProbability returns the current success probability + estimate for a given node pair and amount. The call returns a zero success + probability if no channel is available or if the amount violates min/max + HTLC constraints. + */ + rpc QueryProbability (QueryProbabilityRequest) + returns (QueryProbabilityResponse); + + /* + BuildRoute builds a fully specified route based on a list of hop public + keys. It retrieves the relevant channel policies from the graph in order to + calculate the correct fees and time locks. + */ + rpc BuildRoute (BuildRouteRequest) returns (BuildRouteResponse); + + /* + SubscribeHtlcEvents creates a uni-directional stream from the server to + the client which delivers a stream of htlc events. + */ + rpc SubscribeHtlcEvents (SubscribeHtlcEventsRequest) + returns (stream HtlcEvent); + + /* + Deprecated, use SendPaymentV2. SendPayment attempts to route a payment + described by the passed PaymentRequest to the final destination. The call + returns a stream of payment status updates. + */ + rpc SendPayment (SendPaymentRequest) returns (stream PaymentStatus) { + option deprecated = true; + } + + /* + Deprecated, use TrackPaymentV2. TrackPayment returns an update stream for + the payment identified by the payment hash. + */ + rpc TrackPayment (TrackPaymentRequest) returns (stream PaymentStatus) { + option deprecated = true; + } + + /** + HtlcInterceptor dispatches a bi-directional streaming RPC in which + Forwarded HTLC requests are sent to the client and the client responds with + a boolean that tells LND if this htlc should be intercepted. + In case of interception, the htlc can be either settled, cancelled or + resumed later by using the ResolveHoldForward endpoint. + */ + rpc HtlcInterceptor (stream ForwardHtlcInterceptResponse) + returns (stream ForwardHtlcInterceptRequest); + + /* + UpdateChanStatus attempts to manually set the state of a channel + (enabled, disabled, or auto). A manual "disable" request will cause the + channel to stay disabled until a subsequent manual request of either + "enable" or "auto". + */ + rpc UpdateChanStatus (UpdateChanStatusRequest) + returns (UpdateChanStatusResponse); +} + +message SendPaymentRequest { + // The identity pubkey of the payment recipient + bytes dest = 1; + + /* + Number of satoshis to send. + + The fields amt and amt_msat are mutually exclusive. + */ + int64 amt = 2; + + /* + Number of millisatoshis to send. + + The fields amt and amt_msat are mutually exclusive. + */ + int64 amt_msat = 12; + + // The hash to use within the payment's HTLC + bytes payment_hash = 3; + + /* + The CLTV delta from the current height that should be used to set the + timelock for the final hop. + */ + int32 final_cltv_delta = 4; + + // An optional payment addr to be included within the last hop of the route. + bytes payment_addr = 20; + + /* + A bare-bones invoice for a payment within the Lightning Network. With the + details of the invoice, the sender has all the data necessary to send a + payment to the recipient. The amount in the payment request may be zero. In + that case it is required to set the amt field as well. If no payment request + is specified, the following fields are required: dest, amt and payment_hash. + */ + string payment_request = 5; + + /* + An upper limit on the amount of time we should spend when attempting to + fulfill the payment. This is expressed in seconds. If we cannot make a + successful payment within this time frame, an error will be returned. + This field must be non-zero. + */ + int32 timeout_seconds = 6; + + /* + The maximum number of satoshis that will be paid as a fee of the payment. + If this field is left to the default value of 0, only zero-fee routes will + be considered. This usually means single hop routes connecting directly to + the destination. To send the payment without a fee limit, use max int here. + + The fields fee_limit_sat and fee_limit_msat are mutually exclusive. + */ + int64 fee_limit_sat = 7; + + /* + The maximum number of millisatoshis that will be paid as a fee of the + payment. If this field is left to the default value of 0, only zero-fee + routes will be considered. This usually means single hop routes connecting + directly to the destination. To send the payment without a fee limit, use + max int here. + + The fields fee_limit_sat and fee_limit_msat are mutually exclusive. + */ + int64 fee_limit_msat = 13; + + /* + Deprecated, use outgoing_chan_ids. The channel id of the channel that must + be taken to the first hop. If zero, any channel may be used (unless + outgoing_chan_ids are set). + */ + uint64 outgoing_chan_id = 8 [jstype = JS_STRING, deprecated = true]; + + /* + The channel ids of the channels are allowed for the first hop. If empty, + any channel may be used. + */ + repeated uint64 outgoing_chan_ids = 19; + + /* + The pubkey of the last hop of the route. If empty, any hop may be used. + */ + bytes last_hop_pubkey = 14; + + /* + An optional maximum total time lock for the route. This should not exceed + lnd's `--max-cltv-expiry` setting. If zero, then the value of + `--max-cltv-expiry` is enforced. + */ + int32 cltv_limit = 9; + + /* + Optional route hints to reach the destination through private channels. + */ + repeated lnrpc.RouteHint route_hints = 10; + + /* + An optional field that can be used to pass an arbitrary set of TLV records + to a peer which understands the new records. This can be used to pass + application specific data during the payment attempt. Record types are + required to be in the custom range >= 65536. When using REST, the values + must be encoded as base64. + */ + map dest_custom_records = 11; + + // If set, circular payments to self are permitted. + bool allow_self_payment = 15; + + /* + Features assumed to be supported by the final node. All transitive feature + dependencies must also be set properly. For a given feature bit pair, either + optional or remote may be set, but not both. If this field is nil or empty, + the router will try to load destination features from the graph as a + fallback. + */ + repeated lnrpc.FeatureBit dest_features = 16; + + /* + The maximum number of partial payments that may be use to complete the full + amount. + */ + uint32 max_parts = 17; + + /* + If set, only the final payment update is streamed back. Intermediate updates + that show which htlcs are still in flight are suppressed. + */ + bool no_inflight_updates = 18; + + /* + The largest payment split that should be attempted when making a payment if + splitting is necessary. Setting this value will effectively cause lnd to + split more aggressively, vs only when it thinks it needs to. Note that this + value is in milli-satoshis. + */ + uint64 max_shard_size_msat = 21; + + /* + If set, an AMP-payment will be attempted. + */ + bool amp = 22; + + /* + The time preference for this payment. Set to -1 to optimize for fees + only, to 1 to optimize for reliability only or a value inbetween for a mix. + */ + double time_pref = 23; +} + +message TrackPaymentRequest { + // The hash of the payment to look up. + bytes payment_hash = 1; + + /* + If set, only the final payment update is streamed back. Intermediate updates + that show which htlcs are still in flight are suppressed. + */ + bool no_inflight_updates = 2; +} + +message TrackPaymentsRequest { + /* + If set, only the final payment updates are streamed back. Intermediate + updates that show which htlcs are still in flight are suppressed. + */ + bool no_inflight_updates = 1; +} + +message RouteFeeRequest { + /* + The destination once wishes to obtain a routing fee quote to. + */ + bytes dest = 1; + + /* + The amount one wishes to send to the target destination. + */ + int64 amt_sat = 2; +} + +message RouteFeeResponse { + /* + A lower bound of the estimated fee to the target destination within the + network, expressed in milli-satoshis. + */ + int64 routing_fee_msat = 1; + + /* + An estimate of the worst case time delay that can occur. Note that callers + will still need to factor in the final CLTV delta of the last hop into this + value. + */ + int64 time_lock_delay = 2; +} + +message SendToRouteRequest { + // The payment hash to use for the HTLC. + bytes payment_hash = 1; + + // Route that should be used to attempt to complete the payment. + lnrpc.Route route = 2; + + /* + Whether the payment should be marked as failed when a temporary error is + returned from the given route. Set it to true so the payment won't be + failed unless a terminal error is occurred, such as payment timeout, no + routes, incorrect payment details, or insufficient funds. + */ + bool skip_temp_err = 3; +} + +message SendToRouteResponse { + // The preimage obtained by making the payment. + bytes preimage = 1; + + // The failure message in case the payment failed. + lnrpc.Failure failure = 2; +} + +message ResetMissionControlRequest { +} + +message ResetMissionControlResponse { +} + +message QueryMissionControlRequest { +} + +// QueryMissionControlResponse contains mission control state. +message QueryMissionControlResponse { + reserved 1; + + // Node pair-level mission control state. + repeated PairHistory pairs = 2; +} + +message XImportMissionControlRequest { + // Node pair-level mission control state to be imported. + repeated PairHistory pairs = 1; + + // Whether to force override MC pair history. Note that even with force + // override the failure pair is imported before the success pair and both + // still clamp existing failure/success amounts. + bool force = 2; +} + +message XImportMissionControlResponse { +} + +// PairHistory contains the mission control state for a particular node pair. +message PairHistory { + // The source node pubkey of the pair. + bytes node_from = 1; + + // The destination node pubkey of the pair. + bytes node_to = 2; + + reserved 3, 4, 5, 6; + + PairData history = 7; +} + +message PairData { + // Time of last failure. + int64 fail_time = 1; + + /* + Lowest amount that failed to forward rounded to whole sats. This may be + set to zero if the failure is independent of amount. + */ + int64 fail_amt_sat = 2; + + /* + Lowest amount that failed to forward in millisats. This may be + set to zero if the failure is independent of amount. + */ + int64 fail_amt_msat = 4; + + reserved 3; + + // Time of last success. + int64 success_time = 5; + + // Highest amount that we could successfully forward rounded to whole sats. + int64 success_amt_sat = 6; + + // Highest amount that we could successfully forward in millisats. + int64 success_amt_msat = 7; +} + +message GetMissionControlConfigRequest { +} + +message GetMissionControlConfigResponse { + /* + Mission control's currently active config. + */ + MissionControlConfig config = 1; +} + +message SetMissionControlConfigRequest { + /* + The config to set for mission control. Note that all values *must* be set, + because the full config will be applied. + */ + MissionControlConfig config = 1; +} + +message SetMissionControlConfigResponse { +} + +message MissionControlConfig { + /* + Deprecated, use AprioriParameters. The amount of time mission control will + take to restore a penalized node or channel back to 50% success probability, + expressed in seconds. Setting this value to a higher value will penalize + failures for longer, making mission control less likely to route through + nodes and channels that we have previously recorded failures for. + */ + uint64 half_life_seconds = 1 [deprecated = true]; + + /* + Deprecated, use AprioriParameters. The probability of success mission + control should assign to hop in a route where it has no other information + available. Higher values will make mission control more willing to try hops + that we have no information about, lower values will discourage trying these + hops. + */ + float hop_probability = 2 [deprecated = true]; + + /* + Deprecated, use AprioriParameters. The importance that mission control + should place on historical results, expressed as a value in [0;1]. Setting + this value to 1 will ignore all historical payments and just use the hop + probability to assess the probability of success for each hop. A zero value + ignores hop probability completely and relies entirely on historical + results, unless none are available. + */ + float weight = 3 [deprecated = true]; + + /* + The maximum number of payment results that mission control will store. + */ + uint32 maximum_payment_results = 4; + + /* + The minimum time that must have passed since the previously recorded failure + before we raise the failure amount. + */ + uint64 minimum_failure_relax_interval = 5; + + enum ProbabilityModel { + APRIORI = 0; + BIMODAL = 1; + } + + /* + ProbabilityModel defines which probability estimator should be used in + pathfinding. Note that the bimodal estimator is experimental. + */ + ProbabilityModel model = 6; + + /* + EstimatorConfig is populated dependent on the estimator type. + */ + oneof EstimatorConfig { + AprioriParameters apriori = 7; + BimodalParameters bimodal = 8; + } +} + +message BimodalParameters { + /* + NodeWeight defines how strongly other previous forwardings on channels of a + router should be taken into account when computing a channel's probability + to route. The allowed values are in the range [0, 1], where a value of 0 + means that only direct information about a channel is taken into account. + */ + double node_weight = 1; + + /* + ScaleMsat describes the scale over which channels statistically have some + liquidity left. The value determines how quickly the bimodal distribution + drops off from the edges of a channel. A larger value (compared to typical + channel capacities) means that the drop off is slow and that channel + balances are distributed more uniformly. A small value leads to the + assumption of very unbalanced channels. + */ + uint64 scale_msat = 2; + + /* + DecayTime describes the information decay of knowledge about previous + successes and failures in channels. The smaller the decay time, the quicker + we forget about past forwardings. + */ + uint64 decay_time = 3; +} + +message AprioriParameters { + /* + The amount of time mission control will take to restore a penalized node + or channel back to 50% success probability, expressed in seconds. Setting + this value to a higher value will penalize failures for longer, making + mission control less likely to route through nodes and channels that we + have previously recorded failures for. + */ + uint64 half_life_seconds = 1; + + /* + The probability of success mission control should assign to hop in a route + where it has no other information available. Higher values will make mission + control more willing to try hops that we have no information about, lower + values will discourage trying these hops. + */ + double hop_probability = 2; + + /* + The importance that mission control should place on historical results, + expressed as a value in [0;1]. Setting this value to 1 will ignore all + historical payments and just use the hop probability to assess the + probability of success for each hop. A zero value ignores hop probability + completely and relies entirely on historical results, unless none are + available. + */ + double weight = 3; + + /* + The fraction of a channel's capacity that we consider to have liquidity. For + amounts that come close to or exceed the fraction, an additional penalty is + applied. A value of 1.0 disables the capacity factor. Allowed values are in + [0.75, 1.0]. + */ + double capacity_fraction = 4; +} + +message QueryProbabilityRequest { + // The source node pubkey of the pair. + bytes from_node = 1; + + // The destination node pubkey of the pair. + bytes to_node = 2; + + // The amount for which to calculate a probability. + int64 amt_msat = 3; +} + +message QueryProbabilityResponse { + // The success probability for the requested pair. + double probability = 1; + + // The historical data for the requested pair. + PairData history = 2; +} + +message BuildRouteRequest { + /* + The amount to send expressed in msat. If set to zero, the minimum routable + amount is used. + */ + int64 amt_msat = 1; + + /* + CLTV delta from the current height that should be used for the timelock + of the final hop + */ + int32 final_cltv_delta = 2; + + /* + The channel id of the channel that must be taken to the first hop. If zero, + any channel may be used. + */ + uint64 outgoing_chan_id = 3 [jstype = JS_STRING]; + + /* + A list of hops that defines the route. This does not include the source hop + pubkey. + */ + repeated bytes hop_pubkeys = 4; + + // An optional payment addr to be included within the last hop of the route. + bytes payment_addr = 5; +} + +message BuildRouteResponse { + /* + Fully specified route that can be used to execute the payment. + */ + lnrpc.Route route = 1; +} + +message SubscribeHtlcEventsRequest { +} + +/* +HtlcEvent contains the htlc event that was processed. These are served on a +best-effort basis; events are not persisted, delivery is not guaranteed +(in the event of a crash in the switch, forward events may be lost) and +some events may be replayed upon restart. Events consumed from this package +should be de-duplicated by the htlc's unique combination of incoming and +outgoing channel id and htlc id. [EXPERIMENTAL] +*/ +message HtlcEvent { + /* + The short channel id that the incoming htlc arrived at our node on. This + value is zero for sends. + */ + uint64 incoming_channel_id = 1; + + /* + The short channel id that the outgoing htlc left our node on. This value + is zero for receives. + */ + uint64 outgoing_channel_id = 2; + + /* + Incoming id is the index of the incoming htlc in the incoming channel. + This value is zero for sends. + */ + uint64 incoming_htlc_id = 3; + + /* + Outgoing id is the index of the outgoing htlc in the outgoing channel. + This value is zero for receives. + */ + uint64 outgoing_htlc_id = 4; + + /* + The time in unix nanoseconds that the event occurred. + */ + uint64 timestamp_ns = 5; + + enum EventType { + UNKNOWN = 0; + SEND = 1; + RECEIVE = 2; + FORWARD = 3; + } + + /* + The event type indicates whether the htlc was part of a send, receive or + forward. + */ + EventType event_type = 6; + + oneof event { + ForwardEvent forward_event = 7; + ForwardFailEvent forward_fail_event = 8; + SettleEvent settle_event = 9; + LinkFailEvent link_fail_event = 10; + SubscribedEvent subscribed_event = 11; + FinalHtlcEvent final_htlc_event = 12; + } +} + +message HtlcInfo { + // The timelock on the incoming htlc. + uint32 incoming_timelock = 1; + + // The timelock on the outgoing htlc. + uint32 outgoing_timelock = 2; + + // The amount of the incoming htlc. + uint64 incoming_amt_msat = 3; + + // The amount of the outgoing htlc. + uint64 outgoing_amt_msat = 4; +} + +message ForwardEvent { + // Info contains details about the htlc that was forwarded. + HtlcInfo info = 1; +} + +message ForwardFailEvent { +} + +message SettleEvent { + // The revealed preimage. + bytes preimage = 1; +} + +message FinalHtlcEvent { + bool settled = 1; + bool offchain = 2; +} + +message SubscribedEvent { +} + +message LinkFailEvent { + // Info contains details about the htlc that we failed. + HtlcInfo info = 1; + + // FailureCode is the BOLT error code for the failure. + lnrpc.Failure.FailureCode wire_failure = 2; + + /* + FailureDetail provides additional information about the reason for the + failure. This detail enriches the information provided by the wire message + and may be 'no detail' if the wire message requires no additional metadata. + */ + FailureDetail failure_detail = 3; + + // A string representation of the link failure. + string failure_string = 4; +} + +enum FailureDetail { + UNKNOWN = 0; + NO_DETAIL = 1; + ONION_DECODE = 2; + LINK_NOT_ELIGIBLE = 3; + ON_CHAIN_TIMEOUT = 4; + HTLC_EXCEEDS_MAX = 5; + INSUFFICIENT_BALANCE = 6; + INCOMPLETE_FORWARD = 7; + HTLC_ADD_FAILED = 8; + FORWARDS_DISABLED = 9; + INVOICE_CANCELED = 10; + INVOICE_UNDERPAID = 11; + INVOICE_EXPIRY_TOO_SOON = 12; + INVOICE_NOT_OPEN = 13; + MPP_INVOICE_TIMEOUT = 14; + ADDRESS_MISMATCH = 15; + SET_TOTAL_MISMATCH = 16; + SET_TOTAL_TOO_LOW = 17; + SET_OVERPAID = 18; + UNKNOWN_INVOICE = 19; + INVALID_KEYSEND = 20; + MPP_IN_PROGRESS = 21; + CIRCULAR_ROUTE = 22; +} + +enum PaymentState { + /* + Payment is still in flight. + */ + IN_FLIGHT = 0; + + /* + Payment completed successfully. + */ + SUCCEEDED = 1; + + /* + There are more routes to try, but the payment timeout was exceeded. + */ + FAILED_TIMEOUT = 2; + + /* + All possible routes were tried and failed permanently. Or were no + routes to the destination at all. + */ + FAILED_NO_ROUTE = 3; + + /* + A non-recoverable error has occurred. + */ + FAILED_ERROR = 4; + + /* + Payment details incorrect (unknown hash, invalid amt or + invalid final cltv delta) + */ + FAILED_INCORRECT_PAYMENT_DETAILS = 5; + + /* + Insufficient local balance. + */ + FAILED_INSUFFICIENT_BALANCE = 6; +} + +message PaymentStatus { + // Current state the payment is in. + PaymentState state = 1; + + /* + The pre-image of the payment when state is SUCCEEDED. + */ + bytes preimage = 2; + + reserved 3; + + /* + The HTLCs made in attempt to settle the payment [EXPERIMENTAL]. + */ + repeated lnrpc.HTLCAttempt htlcs = 4; +} + +message CircuitKey { + /// The id of the channel that the is part of this circuit. + uint64 chan_id = 1; + + /// The index of the incoming htlc in the incoming channel. + uint64 htlc_id = 2; +} + +message ForwardHtlcInterceptRequest { + /* + The key of this forwarded htlc. It defines the incoming channel id and + the index in this channel. + */ + CircuitKey incoming_circuit_key = 1; + + // The incoming htlc amount. + uint64 incoming_amount_msat = 5; + + // The incoming htlc expiry. + uint32 incoming_expiry = 6; + + /* + The htlc payment hash. This value is not guaranteed to be unique per + request. + */ + bytes payment_hash = 2; + + // The requested outgoing channel id for this forwarded htlc. Because of + // non-strict forwarding, this isn't necessarily the channel over which the + // packet will be forwarded eventually. A different channel to the same peer + // may be selected as well. + uint64 outgoing_requested_chan_id = 7; + + // The outgoing htlc amount. + uint64 outgoing_amount_msat = 3; + + // The outgoing htlc expiry. + uint32 outgoing_expiry = 4; + + // Any custom records that were present in the payload. + map custom_records = 8; + + // The onion blob for the next hop + bytes onion_blob = 9; + + // The block height at which this htlc will be auto-failed to prevent the + // channel from force-closing. + int32 auto_fail_height = 10; +} + +/** +ForwardHtlcInterceptResponse enables the caller to resolve a previously hold +forward. The caller can choose either to: +- `Resume`: Execute the default behavior (usually forward). +- `Reject`: Fail the htlc backwards. +- `Settle`: Settle this htlc with a given preimage. +*/ +message ForwardHtlcInterceptResponse { + /** + The key of this forwarded htlc. It defines the incoming channel id and + the index in this channel. + */ + CircuitKey incoming_circuit_key = 1; + + // The resolve action for this intercepted htlc. + ResolveHoldForwardAction action = 2; + + // The preimage in case the resolve action is Settle. + bytes preimage = 3; + + // Encrypted failure message in case the resolve action is Fail. + // + // If failure_message is specified, the failure_code field must be set + // to zero. + bytes failure_message = 4; + + // Return the specified failure code in case the resolve action is Fail. The + // message data fields are populated automatically. + // + // If a non-zero failure_code is specified, failure_message must not be set. + // + // For backwards-compatibility reasons, TEMPORARY_CHANNEL_FAILURE is the + // default value for this field. + lnrpc.Failure.FailureCode failure_code = 5; +} + +enum ResolveHoldForwardAction { + SETTLE = 0; + FAIL = 1; + RESUME = 2; +} + +message UpdateChanStatusRequest { + lnrpc.ChannelPoint chan_point = 1; + + ChanStatusAction action = 2; +} + +enum ChanStatusAction { + ENABLE = 0; + DISABLE = 1; + AUTO = 2; +} + +message UpdateChanStatusResponse { +} diff --git a/proto/signrpc/signer.proto b/proto/signrpc/signer.proto new file mode 100644 index 000000000..f704000f9 --- /dev/null +++ b/proto/signrpc/signer.proto @@ -0,0 +1,697 @@ +syntax = "proto3"; + +package signrpc; + +option go_package = "github.com/lightningnetwork/lnd/lnrpc/signrpc"; + +// Signer is a service that gives access to the signing functionality of the +// daemon's wallet. +service Signer { + /* + SignOutputRaw is a method that can be used to generated a signature for a + set of inputs/outputs to a transaction. Each request specifies details + concerning how the outputs should be signed, which keys they should be + signed with, and also any optional tweaks. The return value is a fixed + 64-byte signature (the same format as we use on the wire in Lightning). + + If we are unable to sign using the specified keys, then an error will be + returned. + */ + rpc SignOutputRaw (SignReq) returns (SignResp); + + /* + ComputeInputScript generates a complete InputIndex for the passed + transaction with the signature as defined within the passed SignDescriptor. + This method should be capable of generating the proper input script for both + regular p2wkh/p2tr outputs and p2wkh outputs nested within a regular p2sh + output. + + Note that when using this method to sign inputs belonging to the wallet, + the only items of the SignDescriptor that need to be populated are pkScript + in the TxOut field, the value in that same field, and finally the input + index. + */ + rpc ComputeInputScript (SignReq) returns (InputScriptResp); + + /* + SignMessage signs a message with the key specified in the key locator. The + returned signature is fixed-size LN wire format encoded. + + The main difference to SignMessage in the main RPC is that a specific key is + used to sign the message instead of the node identity private key. + */ + rpc SignMessage (SignMessageReq) returns (SignMessageResp); + + /* + VerifyMessage verifies a signature over a message using the public key + provided. The signature must be fixed-size LN wire format encoded. + + The main difference to VerifyMessage in the main RPC is that the public key + used to sign the message does not have to be a node known to the network. + */ + rpc VerifyMessage (VerifyMessageReq) returns (VerifyMessageResp); + + /* + DeriveSharedKey returns a shared secret key by performing Diffie-Hellman key + derivation between the ephemeral public key in the request and the node's + key specified in the key_desc parameter. Either a key locator or a raw + public key is expected in the key_desc, if neither is supplied, defaults to + the node's identity private key: + P_shared = privKeyNode * ephemeralPubkey + The resulting shared public key is serialized in the compressed format and + hashed with sha256, resulting in the final key length of 256bit. + */ + rpc DeriveSharedKey (SharedKeyRequest) returns (SharedKeyResponse); + + /* + MuSig2CombineKeys (experimental!) is a stateless helper RPC that can be used + to calculate the combined MuSig2 public key from a list of all participating + signers' public keys. This RPC is completely stateless and deterministic and + does not create any signing session. It can be used to determine the Taproot + public key that should be put in an on-chain output once all public keys are + known. A signing session is only needed later when that output should be + _spent_ again. + + NOTE: The MuSig2 BIP is not final yet and therefore this API must be + considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming + releases. Backward compatibility is not guaranteed! + */ + rpc MuSig2CombineKeys (MuSig2CombineKeysRequest) + returns (MuSig2CombineKeysResponse); + + /* + MuSig2CreateSession (experimental!) creates a new MuSig2 signing session + using the local key identified by the key locator. The complete list of all + public keys of all signing parties must be provided, including the public + key of the local signing key. If nonces of other parties are already known, + they can be submitted as well to reduce the number of RPC calls necessary + later on. + + NOTE: The MuSig2 BIP is not final yet and therefore this API must be + considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming + releases. Backward compatibility is not guaranteed! + */ + rpc MuSig2CreateSession (MuSig2SessionRequest) + returns (MuSig2SessionResponse); + + /* + MuSig2RegisterNonces (experimental!) registers one or more public nonces of + other signing participants for a session identified by its ID. This RPC can + be called multiple times until all nonces are registered. + + NOTE: The MuSig2 BIP is not final yet and therefore this API must be + considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming + releases. Backward compatibility is not guaranteed! + */ + rpc MuSig2RegisterNonces (MuSig2RegisterNoncesRequest) + returns (MuSig2RegisterNoncesResponse); + + /* + MuSig2Sign (experimental!) creates a partial signature using the local + signing key that was specified when the session was created. This can only + be called when all public nonces of all participants are known and have been + registered with the session. If this node isn't responsible for combining + all the partial signatures, then the cleanup flag should be set, indicating + that the session can be removed from memory once the signature was produced. + + NOTE: The MuSig2 BIP is not final yet and therefore this API must be + considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming + releases. Backward compatibility is not guaranteed! + */ + rpc MuSig2Sign (MuSig2SignRequest) returns (MuSig2SignResponse); + + /* + MuSig2CombineSig (experimental!) combines the given partial signature(s) + with the local one, if it already exists. Once a partial signature of all + participants is registered, the final signature will be combined and + returned. + + NOTE: The MuSig2 BIP is not final yet and therefore this API must be + considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming + releases. Backward compatibility is not guaranteed! + */ + rpc MuSig2CombineSig (MuSig2CombineSigRequest) + returns (MuSig2CombineSigResponse); + + /* + MuSig2Cleanup (experimental!) allows a caller to clean up a session early in + cases where it's obvious that the signing session won't succeed and the + resources can be released. + + NOTE: The MuSig2 BIP is not final yet and therefore this API must be + considered to be HIGHLY EXPERIMENTAL and subject to change in upcoming + releases. Backward compatibility is not guaranteed! + */ + rpc MuSig2Cleanup (MuSig2CleanupRequest) returns (MuSig2CleanupResponse); +} + +message KeyLocator { + // The family of key being identified. + int32 key_family = 1; + + // The precise index of the key being identified. + int32 key_index = 2; +} + +message KeyDescriptor { + /* + The raw bytes of the public key in the key pair being identified. Either + this or the KeyLocator must be specified. + */ + bytes raw_key_bytes = 1; + + /* + The key locator that identifies which private key to use for signing. + Either this or the raw bytes of the target public key must be specified. + */ + KeyLocator key_loc = 2; +} + +message TxOut { + // The value of the output being spent. + int64 value = 1; + + // The script of the output being spent. + bytes pk_script = 2; +} + +enum SignMethod { + /* + Specifies that a SegWit v0 (p2wkh, np2wkh, p2wsh) input script should be + signed. + */ + SIGN_METHOD_WITNESS_V0 = 0; + + /* + Specifies that a SegWit v1 (p2tr) input should be signed by using the + BIP0086 method (commit to internal key only). + */ + SIGN_METHOD_TAPROOT_KEY_SPEND_BIP0086 = 1; + + /* + Specifies that a SegWit v1 (p2tr) input should be signed by using a given + taproot hash to commit to in addition to the internal key. + */ + SIGN_METHOD_TAPROOT_KEY_SPEND = 2; + + /* + Specifies that a SegWit v1 (p2tr) input should be spent using the script + path and that a specific leaf script should be signed for. + */ + SIGN_METHOD_TAPROOT_SCRIPT_SPEND = 3; +} + +message SignDescriptor { + /* + A descriptor that precisely describes *which* key to use for signing. This + may provide the raw public key directly, or require the Signer to re-derive + the key according to the populated derivation path. + + Note that if the key descriptor was obtained through walletrpc.DeriveKey, + then the key locator MUST always be provided, since the derived keys are not + persisted unlike with DeriveNextKey. + */ + KeyDescriptor key_desc = 1; + + /* + A scalar value that will be added to the private key corresponding to the + above public key to obtain the private key to be used to sign this input. + This value is typically derived via the following computation: + + * derivedKey = privkey + sha256(perCommitmentPoint || pubKey) mod N + */ + bytes single_tweak = 2; + + /* + A private key that will be used in combination with its corresponding + private key to derive the private key that is to be used to sign the target + input. Within the Lightning protocol, this value is typically the + commitment secret from a previously revoked commitment transaction. This + value is in combination with two hash values, and the original private key + to derive the private key to be used when signing. + + * k = (privKey*sha256(pubKey || tweakPub) + + tweakPriv*sha256(tweakPub || pubKey)) mod N + */ + bytes double_tweak = 3; + + /* + The 32 byte input to the taproot tweak derivation that is used to derive + the output key from an internal key: outputKey = internalKey + + tagged_hash("tapTweak", internalKey || tapTweak). + + When doing a BIP 86 spend, this field can be an empty byte slice. + + When doing a normal key path spend, with the output key committing to an + actual script root, then this field should be: the tapscript root hash. + */ + bytes tap_tweak = 10; + + /* + The full script required to properly redeem the output. This field will + only be populated if a p2tr, p2wsh or a p2sh output is being signed. If a + taproot script path spend is being attempted, then this should be the raw + leaf script. + */ + bytes witness_script = 4; + + /* + A description of the output being spent. The value and script MUST be + provided. + */ + TxOut output = 5; + + /* + The target sighash type that should be used when generating the final + sighash, and signature. + */ + uint32 sighash = 7; + + /* + The target input within the transaction that should be signed. + */ + int32 input_index = 8; + + /* + The sign method specifies how the input should be signed. Depending on the + method, either the tap_tweak, witness_script or both need to be specified. + Defaults to SegWit v0 signing to be backward compatible with older RPC + clients. + */ + SignMethod sign_method = 9; +} + +message SignReq { + // The raw bytes of the transaction to be signed. + bytes raw_tx_bytes = 1; + + // A set of sign descriptors, for each input to be signed. + repeated SignDescriptor sign_descs = 2; + + /* + The full list of UTXO information for each of the inputs being spent. This + is required when spending one or more taproot (SegWit v1) outputs. + */ + repeated TxOut prev_outputs = 3; +} + +message SignResp { + /* + A set of signatures realized in a fixed 64-byte format ordered in ascending + input order. + */ + repeated bytes raw_sigs = 1; +} + +message InputScript { + // The serializes witness stack for the specified input. + repeated bytes witness = 1; + + /* + The optional sig script for the specified witness that will only be set if + the input specified is a nested p2sh witness program. + */ + bytes sig_script = 2; +} + +message InputScriptResp { + // The set of fully valid input scripts requested. + repeated InputScript input_scripts = 1; +} + +message SignMessageReq { + /* + The message to be signed. When using REST, this field must be encoded as + base64. + */ + bytes msg = 1; + + // The key locator that identifies which key to use for signing. + KeyLocator key_loc = 2; + + // Double-SHA256 hash instead of just the default single round. + bool double_hash = 3; + + /* + Use the compact (pubkey recoverable) format instead of the raw lnwire + format. This option cannot be used with Schnorr signatures. + */ + bool compact_sig = 4; + + /* + Use Schnorr signature. This option cannot be used with compact format. + */ + bool schnorr_sig = 5; + + /* + The optional Taproot tweak bytes to apply to the private key before creating + a Schnorr signature. The private key is tweaked as described in BIP-341: + privKey + h_tapTweak(internalKey || tapTweak) + */ + bytes schnorr_sig_tap_tweak = 6; +} +message SignMessageResp { + /* + The signature for the given message in the fixed-size LN wire format. + */ + bytes signature = 1; +} + +message VerifyMessageReq { + // The message over which the signature is to be verified. When using + // REST, this field must be encoded as base64. + bytes msg = 1; + + /* + The fixed-size LN wire encoded signature to be verified over the given + message. When using REST, this field must be encoded as base64. + */ + bytes signature = 2; + + /* + The public key the signature has to be valid for. When using REST, this + field must be encoded as base64. If the is_schnorr_sig option is true, then + the public key is expected to be in the 32-byte x-only serialization + according to BIP-340. + */ + bytes pubkey = 3; + + /* + Specifies if the signature is a Schnorr signature. + */ + bool is_schnorr_sig = 4; +} + +message VerifyMessageResp { + // Whether the signature was valid over the given message. + bool valid = 1; +} + +message SharedKeyRequest { + // The ephemeral public key to use for the DH key derivation. + bytes ephemeral_pubkey = 1; + + /* + Deprecated. The optional key locator of the local key that should be used. + If this parameter is not set then the node's identity private key will be + used. + */ + KeyLocator key_loc = 2 [deprecated = true]; + + /* + A key descriptor describes the key used for performing ECDH. Either a key + locator or a raw public key is expected, if neither is supplied, defaults to + the node's identity private key. + */ + KeyDescriptor key_desc = 3; +} + +message SharedKeyResponse { + // The shared public key, hashed with sha256. + bytes shared_key = 1; +} + +message TweakDesc { + /* + Tweak is the 32-byte value that will modify the public key. + */ + bytes tweak = 1; + + /* + Specifies if the target key should be converted to an x-only public key + before tweaking. If true, then the public key will be mapped to an x-only + key before the tweaking operation is applied. + */ + bool is_x_only = 2; +} + +message TaprootTweakDesc { + /* + The root hash of the tapscript tree if a script path is committed to. If + the MuSig2 key put on chain doesn't also commit to a script path (BIP-0086 + key spend only), then this needs to be empty and the key_spend_only field + below must be set to true. This is required because gRPC cannot + differentiate between a zero-size byte slice and a nil byte slice (both + would be serialized the same way). So the extra boolean is required. + */ + bytes script_root = 1; + + /* + Indicates that the above script_root is expected to be empty because this + is a BIP-0086 key spend only commitment where only the internal key is + committed to instead of also including a script root hash. + */ + bool key_spend_only = 2; +} + +enum MuSig2Version { + /* + The default value on the RPC is zero for enums so we need to represent an + invalid/undefined version by default to make sure clients upgrade their + software to set the version explicitly. + */ + MUSIG2_VERSION_UNDEFINED = 0; + + /* + The version of MuSig2 that lnd 0.15.x shipped with, which corresponds to the + version v0.4.0 of the MuSig2 BIP draft. + */ + MUSIG2_VERSION_V040 = 1; + + /* + The current version of MuSig2 which corresponds to the version v1.0.0rc2 of + the MuSig2 BIP draft. + */ + MUSIG2_VERSION_V100RC2 = 2; +} + +message MuSig2CombineKeysRequest { + /* + A list of all public keys (serialized in 32-byte x-only format for v0.4.0 + and 33-byte compressed format for v1.0.0rc2!) participating in the signing + session. The list will always be sorted lexicographically internally. This + must include the local key which is described by the above key_loc. + */ + repeated bytes all_signer_pubkeys = 1; + + /* + A series of optional generic tweaks to be applied to the the aggregated + public key. + */ + repeated TweakDesc tweaks = 2; + + /* + An optional taproot specific tweak that must be specified if the MuSig2 + combined key will be used as the main taproot key of a taproot output + on-chain. + */ + TaprootTweakDesc taproot_tweak = 3; + + /* + The mandatory version of the MuSig2 BIP draft to use. This is necessary to + differentiate between the changes that were made to the BIP while this + experimental RPC was already released. Some of those changes affect how the + combined key and nonces are created. + */ + MuSig2Version version = 4; +} + +message MuSig2CombineKeysResponse { + /* + The combined public key (in the 32-byte x-only format) with all tweaks + applied to it. If a taproot tweak is specified, this corresponds to the + taproot key that can be put into the on-chain output. + */ + bytes combined_key = 1; + + /* + The raw combined public key (in the 32-byte x-only format) before any tweaks + are applied to it. If a taproot tweak is specified, this corresponds to the + internal key that needs to be put into the witness if the script spend path + is used. + */ + bytes taproot_internal_key = 2; + + /* + The version of the MuSig2 BIP that was used to combine the keys. + */ + MuSig2Version version = 4; +} + +message MuSig2SessionRequest { + /* + The key locator that identifies which key to use for signing. + */ + KeyLocator key_loc = 1; + + /* + A list of all public keys (serialized in 32-byte x-only format for v0.4.0 + and 33-byte compressed format for v1.0.0rc2!) participating in the signing + session. The list will always be sorted lexicographically internally. This + must include the local key which is described by the above key_loc. + */ + repeated bytes all_signer_pubkeys = 2; + + /* + An optional list of all public nonces of other signing participants that + might already be known. + */ + repeated bytes other_signer_public_nonces = 3; + + /* + A series of optional generic tweaks to be applied to the the aggregated + public key. + */ + repeated TweakDesc tweaks = 4; + + /* + An optional taproot specific tweak that must be specified if the MuSig2 + combined key will be used as the main taproot key of a taproot output + on-chain. + */ + TaprootTweakDesc taproot_tweak = 5; + + /* + The mandatory version of the MuSig2 BIP draft to use. This is necessary to + differentiate between the changes that were made to the BIP while this + experimental RPC was already released. Some of those changes affect how the + combined key and nonces are created. + */ + MuSig2Version version = 6; + + /* + A set of pre generated secret local nonces to use in the musig2 session. + This field is optional. This can be useful for protocols that need to send + nonces ahead of time before the set of signer keys are known. This value + MUST be 97 bytes and be the concatenation of two CSPRNG generated 32 byte + values and local public key used for signing as specified in the key_loc + field. + */ + bytes pregenerated_local_nonce = 7; +} + +message MuSig2SessionResponse { + /* + The unique ID that represents this signing session. A session can be used + for producing a signature a single time. If the signing fails for any + reason, a new session with the same participants needs to be created. + */ + bytes session_id = 1; + + /* + The combined public key (in the 32-byte x-only format) with all tweaks + applied to it. If a taproot tweak is specified, this corresponds to the + taproot key that can be put into the on-chain output. + */ + bytes combined_key = 2; + + /* + The raw combined public key (in the 32-byte x-only format) before any tweaks + are applied to it. If a taproot tweak is specified, this corresponds to the + internal key that needs to be put into the witness if the script spend path + is used. + */ + bytes taproot_internal_key = 3; + + /* + The two public nonces the local signer uses, combined into a single value + of 66 bytes. Can be split into the two 33-byte points to get the individual + nonces. + */ + bytes local_public_nonces = 4; + + /* + Indicates whether all nonces required to start the signing process are known + now. + */ + bool have_all_nonces = 5; + + /* + The version of the MuSig2 BIP that was used to create the session. + */ + MuSig2Version version = 6; +} + +message MuSig2RegisterNoncesRequest { + /* + The unique ID of the signing session those nonces should be registered with. + */ + bytes session_id = 1; + + /* + A list of all public nonces of other signing participants that should be + registered. + */ + repeated bytes other_signer_public_nonces = 3; +} + +message MuSig2RegisterNoncesResponse { + /* + Indicates whether all nonces required to start the signing process are known + now. + */ + bool have_all_nonces = 1; +} + +message MuSig2SignRequest { + /* + The unique ID of the signing session to use for signing. + */ + bytes session_id = 1; + + /* + The 32-byte SHA256 digest of the message to sign. + */ + bytes message_digest = 2; + + /* + Cleanup indicates that after signing, the session state can be cleaned up, + since another participant is going to be responsible for combining the + partial signatures. + */ + bool cleanup = 3; +} + +message MuSig2SignResponse { + /* + The partial signature created by the local signer. + */ + bytes local_partial_signature = 1; +} + +message MuSig2CombineSigRequest { + /* + The unique ID of the signing session to combine the signatures for. + */ + bytes session_id = 1; + + /* + The list of all other participants' partial signatures to add to the current + session. + */ + repeated bytes other_partial_signatures = 2; +} + +message MuSig2CombineSigResponse { + /* + Indicates whether all partial signatures required to create a final, full + signature are known yet. If this is true, then the final_signature field is + set, otherwise it is empty. + */ + bool have_all_signatures = 1; + + /* + The final, full signature that is valid for the combined public key. + */ + bytes final_signature = 2; +} + +message MuSig2CleanupRequest { + /* + The unique ID of the signing session that should be removed/cleaned up. + */ + bytes session_id = 1; +} + +message MuSig2CleanupResponse { +} diff --git a/proto/stateservice.proto b/proto/stateservice.proto new file mode 100644 index 000000000..97a78d31a --- /dev/null +++ b/proto/stateservice.proto @@ -0,0 +1,73 @@ +syntax = "proto3"; + +package lnrpc; + +option go_package = "github.com/lightningnetwork/lnd/lnrpc"; + +/* + * Comments in this file will be directly parsed into the API + * Documentation as descriptions of the associated method, message, or field. + * These descriptions should go right above the definition of the object, and + * can be in either block or // comment format. + * + * An RPC method can be matched to an lncli command by placing a line in the + * beginning of the description in exactly the following format: + * lncli: `methodname` + * + * Failure to specify the exact name of the command will cause documentation + * generation to fail. + * + * More information on how exactly the gRPC documentation is generated from + * this proto file can be found here: + * https://github.com/lightninglabs/lightning-api + */ + +// State service is a always running service that exposes the current state of +// the wallet and RPC server. +service State { + // SubscribeState subscribes to the state of the wallet. The current wallet + // state will always be delivered immediately. + rpc SubscribeState (SubscribeStateRequest) + returns (stream SubscribeStateResponse); + + // GetState returns the current wallet state without streaming further + // changes. + rpc GetState (GetStateRequest) returns (GetStateResponse); +} + +enum WalletState { + // NON_EXISTING means that the wallet has not yet been initialized. + NON_EXISTING = 0; + + // LOCKED means that the wallet is locked and requires a password to unlock. + LOCKED = 1; + + // UNLOCKED means that the wallet was unlocked successfully, but RPC server + // isn't ready. + UNLOCKED = 2; + + // RPC_ACTIVE means that the lnd server is active but not fully ready for + // calls. + RPC_ACTIVE = 3; + + // SERVER_ACTIVE means that the lnd server is ready to accept calls. + SERVER_ACTIVE = 4; + + // WAITING_TO_START means that node is waiting to become the leader in a + // cluster and is not started yet. + WAITING_TO_START = 255; +} + +message SubscribeStateRequest { +} + +message SubscribeStateResponse { + WalletState state = 1; +} + +message GetStateRequest { +} + +message GetStateResponse { + WalletState state = 1; +} diff --git a/proto/taprootassets.proto b/proto/taprootassets.proto new file mode 100644 index 000000000..042d5dcb3 --- /dev/null +++ b/proto/taprootassets.proto @@ -0,0 +1,1025 @@ +syntax = "proto3"; + +package taprpc; + +option go_package = "github.com/lightninglabs/taproot-assets/taprpc"; + +service TaprootAssets { + /* tapcli: `assets list` + ListAssets lists the set of assets owned by the target daemon. + */ + rpc ListAssets (ListAssetRequest) returns (ListAssetResponse); + + /* tapcli: `assets utxos` + ListUtxos lists the UTXOs managed by the target daemon, and the assets they + hold. + */ + rpc ListUtxos (ListUtxosRequest) returns (ListUtxosResponse); + + /* tapcli: `assets groups` + ListGroups lists the asset groups known to the target daemon, and the assets + held in each group. + */ + rpc ListGroups (ListGroupsRequest) returns (ListGroupsResponse); + + /* tapcli: `assets balance` + ListBalances lists asset balances + */ + rpc ListBalances (ListBalancesRequest) returns (ListBalancesResponse); + + /* tapcli: `assets transfers` + ListTransfers lists outbound asset transfers tracked by the target daemon. + */ + rpc ListTransfers (ListTransfersRequest) returns (ListTransfersResponse); + + /* tapcli: `stop` + StopDaemon will send a shutdown request to the interrupt handler, triggering + a graceful shutdown of the daemon. + */ + rpc StopDaemon (StopRequest) returns (StopResponse); + + /* tapcli: `debuglevel` + DebugLevel allows a caller to programmatically set the logging verbosity of + tapd. The logging can be targeted according to a coarse daemon-wide logging + level, or in a granular fashion to specify the logging for a target + sub-system. + */ + rpc DebugLevel (DebugLevelRequest) returns (DebugLevelResponse); + + /* tapcli: `addrs query` + QueryAddrs queries the set of Taproot Asset addresses stored in the + database. + */ + rpc QueryAddrs (QueryAddrRequest) returns (QueryAddrResponse); + + /* tapcli: `addrs new` + NewAddr makes a new address from the set of request params. + */ + rpc NewAddr (NewAddrRequest) returns (Addr); + + /* tapcli: `addrs decode` + DecodeAddr decode a Taproot Asset address into a partial asset message that + represents the asset it wants to receive. + */ + rpc DecodeAddr (DecodeAddrRequest) returns (Addr); + + /* tapcli: `addrs receives` + List all receives for incoming asset transfers for addresses that were + created previously. + */ + rpc AddrReceives (AddrReceivesRequest) returns (AddrReceivesResponse); + + /* tapcli: `proofs verify` + VerifyProof attempts to verify a given proof file that claims to be anchored + at the specified genesis point. + */ + rpc VerifyProof (ProofFile) returns (VerifyProofResponse); + + /* tapcli: `proofs decode` + DecodeProof attempts to decode a given proof file into human readable + format. + */ + rpc DecodeProof (DecodeProofRequest) returns (DecodeProofResponse); + + /* tapcli: `proofs export` + ExportProof exports the latest raw proof file anchored at the specified + script_key. + */ + rpc ExportProof (ExportProofRequest) returns (ProofFile); + + /* tapcli: `assets send` + SendAsset uses one or multiple passed Taproot Asset address(es) to attempt + to complete an asset send. The method returns information w.r.t the on chain + send, as well as the proof file information the receiver needs to fully + receive the asset. + */ + rpc SendAsset (SendAssetRequest) returns (SendAssetResponse); + + /* tapcli: `assets burn` + BurnAsset burns the given number of units of a given asset by sending them + to a provably un-spendable script key. Burning means irrevocably destroying + a certain number of assets, reducing the total supply of the asset. Because + burning is such a destructive and non-reversible operation, some specific + values need to be set in the request to avoid accidental burns. + */ + rpc BurnAsset (BurnAssetRequest) returns (BurnAssetResponse); + + /* tapcli: `getinfo` + GetInfo returns the information for the node. + */ + rpc GetInfo (GetInfoRequest) returns (GetInfoResponse); + + /* + SubscribeSendAssetEventNtfns registers a subscription to the event + notification stream which relates to the asset sending process. + */ + rpc SubscribeSendAssetEventNtfns (SubscribeSendAssetEventNtfnsRequest) + returns (stream SendAssetEvent); + + /* + FetchAssetMeta allows a caller to fetch the reveal meta data for an asset + either by the asset ID for that asset, or a meta hash. + */ + rpc FetchAssetMeta (FetchAssetMetaRequest) returns (AssetMeta); +} + +enum AssetType { + /* + Indicates that an asset is capable of being split/merged, with each of the + units being fungible, even across a key asset ID boundary (assuming the + key group is the same). + */ + NORMAL = 0; + + /* + Indicates that an asset is a collectible, meaning that each of the other + items under the same key group are not fully fungible with each other. + Collectibles also cannot be split or merged. + */ + COLLECTIBLE = 1; +} + +enum AssetMetaType { + /* + Opaque is used for asset meta blobs that have no true structure and instead + should be interpreted as opaque blobs. + */ + META_TYPE_OPAQUE = 0; +} + +message AssetMeta { + /* + The raw data of the asset meta data. Based on the type below, this may be + structured data such as a text file or PDF. The size of the data is limited + to 1MiB. + */ + bytes data = 1; + + // The type of the asset meta data. + AssetMetaType type = 2; + + /* + The hash of the meta. This is the hash of the TLV serialization of the meta + itself. + */ + bytes meta_hash = 3; +} + +message ListAssetRequest { + bool with_witness = 1; + bool include_spent = 2; + bool include_leased = 3; +} + +message AnchorInfo { + // The transaction that anchors the Taproot Asset commitment where the asset + // resides. + bytes anchor_tx = 1; + + // The txid of the above transaction. + string anchor_txid = 2; + + // The block hash the contains the anchor transaction above. + string anchor_block_hash = 3; + + // The outpoint (txid:vout) that stores the Taproot Asset commitment. + string anchor_outpoint = 4; + + /* + The raw internal key that was used to create the anchor Taproot output key. + */ + bytes internal_key = 5; + + /* + The Taproot merkle root hash of the anchor output the asset was committed + to. If there is no Tapscript sibling, this is equal to the Taproot Asset + root commitment hash. + */ + bytes merkle_root = 6; + + /* + The serialized preimage of a Tapscript sibling, if there was one. If this + is empty, then the merkle_root hash is equal to the Taproot root hash of the + anchor output. + */ + bytes tapscript_sibling = 7; + + // The height of the block which contains the anchor transaction. + uint32 block_height = 8; +} + +message GenesisInfo { + // The first outpoint of the transaction that created the asset (txid:vout). + string genesis_point = 1; + + // The name of the asset. + string name = 2; + + // The hash of the meta data for this genesis asset. + bytes meta_hash = 3; + + // The asset ID that uniquely identifies the asset. + bytes asset_id = 4; + + /* + The index of the output that carries the unique Taproot Asset commitment in + the genesis transaction. + */ + uint32 output_index = 5; + + // The version of the Taproot Asset commitment that created this asset. + int32 version = 6; +} + +message AssetGroup { + // The raw group key which is a normal public key. + bytes raw_group_key = 1; + + /* + The tweaked group key, which is derived based on the genesis point and also + asset type. + */ + bytes tweaked_group_key = 2; + + /* + A witness that authorizes a specific asset to be part of the asset group + specified by the above key. + */ + bytes asset_witness = 3; + + // TODO(jhb): update to include tapscript_root +} + +message GroupKeyReveal { + // The raw group key which is a normal public key. + bytes raw_group_key = 1; + + // The tapscript root included in the tweaked group key, which may be empty. + bytes tapscript_root = 2; +} + +message GenesisReveal { + // The base genesis information in the genesis reveal. + GenesisInfo genesis_base_reveal = 1; + + // The asset type, not included in the base genesis info. + AssetType asset_type = 2; +} + +enum AssetVersion { + // ASSET_VERSION_V0 is the default asset version. This version will include + // the witness vector in the leaf for a tap commitment. + ASSET_VERSION_V0 = 0; + + // ASSET_VERSION_V1 is the asset version that leaves out the witness vector + // from the MS-SMT leaf encoding. + ASSET_VERSION_V1 = 1; +} + +message Asset { + // The version of the Taproot Asset. + AssetVersion version = 1; + + // The base genesis information of an asset. This information never changes. + GenesisInfo asset_genesis = 2; + + // The type of the asset. + AssetType asset_type = 3; + + // The total amount of the asset stored in this Taproot Asset UTXO. + uint64 amount = 4; + + // An optional locktime, as with Bitcoin transactions. + int32 lock_time = 5; + + // An optional relative lock time, same as Bitcoin transactions. + int32 relative_lock_time = 6; + + // The version of the script, only version 0 is defined at present. + int32 script_version = 7; + + // The script key of the asset, which can be spent under Taproot semantics. + bytes script_key = 9; + + // Indicates whether the script key is known to the wallet of the lnd node + // connected to the Taproot Asset daemon. + bool script_key_is_local = 10; + + // The information related to the key group of an asset (if it exists). + AssetGroup asset_group = 11; + + // Describes where in the chain the asset is currently anchored. + AnchorInfo chain_anchor = 12; + + repeated PrevWitness prev_witnesses = 13; + + // Indicates whether the asset has been spent. + bool is_spent = 14; + + // If the asset has been leased, this is the owner (application ID) of the + // lease. + bytes lease_owner = 15; + + // If the asset has been leased, this is the expiry of the lease as a Unix + // timestamp in seconds. + int64 lease_expiry = 16; + + // Indicates whether this transfer was an asset burn. If true, the number of + // assets in this output are destroyed and can no longer be spent. + bool is_burn = 17; +} + +message PrevWitness { + PrevInputAsset prev_id = 1; + + repeated bytes tx_witness = 2; + + SplitCommitment split_commitment = 3; +} + +message SplitCommitment { + Asset root_asset = 1; +} + +message ListAssetResponse { + repeated Asset assets = 1; +} + +message ListUtxosRequest { + bool include_leased = 1; +} + +message ManagedUtxo { + // The outpoint of the UTXO. + string out_point = 1; + + // The UTXO amount in satoshis. + int64 amt_sat = 2; + + // The internal key used for the on-chain output. + bytes internal_key = 3; + + // The Taproot Asset root commitment hash. + bytes taproot_asset_root = 4; + + /* + The Taproot merkle root hash committed to by the outpoint of this UTXO. + If there is no Tapscript sibling, this is equal to the Taproot Asset root + commitment hash. + */ + bytes merkle_root = 5; + + // The assets held at this UTXO. + repeated Asset assets = 6; +} + +message ListUtxosResponse { + // The set of UTXOs managed by the daemon. + map managed_utxos = 1; +} + +message ListGroupsRequest { +} + +message AssetHumanReadable { + // The ID of the asset. + bytes id = 1; + + // The amount of the asset. + uint64 amount = 2; + + // An optional locktime, as with Bitcoin transactions. + int32 lock_time = 3; + + // An optional relative locktime, as with Bitcoin transactions. + int32 relative_lock_time = 4; + + // The name of the asset. + string tag = 5; + + // The metadata hash of the asset. + bytes meta_hash = 6; + + // The type of the asset. + AssetType type = 7; + + // The version of the asset. + AssetVersion version = 8; +} + +message GroupedAssets { + // A list of assets with the same group key. + repeated AssetHumanReadable assets = 1; +} + +message ListGroupsResponse { + // The set of assets with a group key. + map groups = 1; +} + +message ListBalancesRequest { + oneof group_by { + // Group results by asset IDs. + bool asset_id = 1; + + // Group results by group keys. + bool group_key = 2; + } + + // If the query results should grouped by asset ids, then an optional asset + // filter may be provided to query balance of a specific asset. + bytes asset_filter = 3; + + // If the query results should be grouped by group keys, then an optional + // group key filter may be provided to query the balance of a specific + // asset group. + bytes group_key_filter = 4; +} + +message AssetBalance { + // The base genesis information of an asset. This information never changes. + GenesisInfo asset_genesis = 1; + + // The type of the asset. + AssetType asset_type = 2; + + // The balance of the asset owned by the target daemon. + uint64 balance = 3; +} + +message AssetGroupBalance { + // The group key or nil aggregating assets that don't have a group. + bytes group_key = 1; + + // The total balance of the assets in the group. + uint64 balance = 2; +} + +message ListBalancesResponse { + map asset_balances = 1; + + map asset_group_balances = 2; +} + +message ListTransfersRequest { +} + +message ListTransfersResponse { + // The unordered list of outgoing asset transfers. + repeated AssetTransfer transfers = 1; +} + +message AssetTransfer { + int64 transfer_timestamp = 1; + + // The new transaction that commits to the set of Taproot Assets found + // at the above new anchor point. + bytes anchor_tx_hash = 2; + + uint32 anchor_tx_height_hint = 3; + + int64 anchor_tx_chain_fees = 4; + + // Describes the set of spent assets. + repeated TransferInput inputs = 5; + + // Describes the set of newly created asset outputs. + repeated TransferOutput outputs = 6; +} + +message TransferInput { + // The old/current location of the Taproot Asset commitment that was spent + // as an input. + string anchor_point = 1; + + // The ID of the asset that was spent. + bytes asset_id = 2; + + // The script key of the asset that was spent. + bytes script_key = 3; + + // The amount of the asset that was spent. + uint64 amount = 4; +} + +message TransferOutputAnchor { + // The new location of the Taproot Asset commitment that was created on + // chain. + string outpoint = 1; + + int64 value = 2; + + bytes internal_key = 3; + + bytes taproot_asset_root = 4; + + bytes merkle_root = 5; + + bytes tapscript_sibling = 6; + + uint32 num_passive_assets = 7; +} + +enum OutputType { + // OUTPUT_TYPE_SIMPLE is a plain full-value or split output that is not a + // split root and does not carry passive assets. In case of a split, the + // asset of this output has a split commitment. + OUTPUT_TYPE_SIMPLE = 0; + + // OUTPUT_TYPE_SPLIT_ROOT is a split root output that carries the change + // from a split or a tombstone from a non-interactive full value send + // output. In either case, the asset of this output has a tx witness. + OUTPUT_TYPE_SPLIT_ROOT = 1; + + // OUTPUT_TYPE_PASSIVE_ASSETS_ONLY indicates that this output only carries + // passive assets and therefore the asset in this output is nil. The passive + // assets themselves are signed in their own virtual transactions and + // are not present in this packet. + OUTPUT_TYPE_PASSIVE_ASSETS_ONLY = 2; + + // OUTPUT_TYPE_PASSIVE_SPLIT_ROOT is a split root output that carries the + // change from a split or a tombstone from a non-interactive full value send + // output, as well as passive assets. + OUTPUT_TYPE_PASSIVE_SPLIT_ROOT = 3; + + // OUTPUT_TYPE_SIMPLE_PASSIVE_ASSETS is a plain full-value interactive send + // output that also carries passive assets. This is a special case where we + // send the full value of a single asset in a commitment to a new script + // key, but also carry passive assets in the same output. This is useful for + // key rotation (send-to-self) scenarios or asset burns where we burn the + // full supply of a single asset within a commitment. + OUTPUT_TYPE_SIMPLE_PASSIVE_ASSETS = 4; +} + +message TransferOutput { + TransferOutputAnchor anchor = 1; + + bytes script_key = 2; + + bool script_key_is_local = 3; + + uint64 amount = 4; + + // The new individual transition proof (not a full proof file) that proves + // the inclusion of the new asset within the new AnchorTx. + bytes new_proof_blob = 5; + + bytes split_commit_root_hash = 6; + + OutputType output_type = 7; + + AssetVersion asset_version = 8; +} + +message StopRequest { +} + +message StopResponse { +} + +message DebugLevelRequest { + // If true, all the valid debug sub-systems will be returned. + bool show = 1; + + string level_spec = 2; +} +message DebugLevelResponse { + string sub_systems = 1; +} + +message Addr { + // The bech32 encoded Taproot Asset address. + string encoded = 1; + + // The asset ID that uniquely identifies the asset. + bytes asset_id = 2; + + // The type of the asset. + AssetType asset_type = 3; + + // The total amount of the asset stored in this Taproot Asset UTXO. + uint64 amount = 4; + + // The group key of the asset (if it exists) + bytes group_key = 5; + + /* + The specific script key the asset must commit to in order to transfer + ownership to the creator of the address. + */ + bytes script_key = 6; + + // The internal key used for the on-chain output. + bytes internal_key = 7; + + /* + The optional serialized tapscript sibling preimage to use for the receiving + asset. This is usually empty as it is only needed when there should be an + additional script path in the Taproot tree alongside the Taproot Asset + commitment of the asset. + */ + bytes tapscript_sibling = 8; + + /* + The tweaked internal key that commits to the asset and represents the + on-chain output key the Bitcoin transaction must send to in order to + transfer assets described in this address. + */ + bytes taproot_output_key = 9; + + // The address of the proof courier service used in proof transfer. + string proof_courier_addr = 10; + + // The asset version of the address. + AssetVersion asset_version = 11; +} + +message QueryAddrRequest { + /* + If set, then only addresses created after this Unix timestamp will be + returned. + */ + int64 created_after = 1; + + /* + If set, then only addresses created before this Unix timestamp will be + returned. + */ + int64 created_before = 2; + + // The max number of addresses that should be returned. + int32 limit = 3; + + // The offset from the addresses that should be returned. + int32 offset = 4; +} + +message QueryAddrResponse { + repeated Addr addrs = 1; +} + +message NewAddrRequest { + bytes asset_id = 1; + + uint64 amt = 2; + + /* + The optional script key that the receiving asset should be locked to. If no + script key is provided, a normal BIP-86 key will be derived from the + underlying wallet. + + NOTE: The script_key and internal_key fields should either both be set or + both be empty. + */ + ScriptKey script_key = 3; + + /* + The optional internal key of the receiving BTC level transaction output on + which the receiving asset transfers will be committed to. If no internal key + is provided, a key will be derived from the underlying wallet. + + NOTE: The script_key and internal_key fields should either both be set or + both be empty. + */ + KeyDescriptor internal_key = 4; + + /* + The optional serialized tapscript sibling preimage to use for the receiving + asset. This is usually empty as it is only needed when there should be an + additional script path in the Taproot tree alongside the Taproot Asset + commitment of the asset. + */ + bytes tapscript_sibling = 5; + + /* + An optional proof courier address for use in proof transfer. If unspecified, + the daemon configured default address will be used. + */ + string proof_courier_addr = 6; + + /* + The asset version to use when sending/receiving to/from this address. + */ + AssetVersion asset_version = 7; +} + +message ScriptKey { + /* + The full Taproot output key the asset is locked to. This is either a BIP-86 + key if the tap_tweak below is empty, or a key with the tap tweak applied to + it. + */ + bytes pub_key = 1; + + /* + The key descriptor describing the internal key of the above Taproot key. + */ + KeyDescriptor key_desc = 2; + + /* + The optional Taproot tweak to apply to the above internal key. If this is + empty then a BIP-86 style tweak is applied to the internal key. + */ + bytes tap_tweak = 3; +} + +message KeyLocator { + /* + The family of key being identified. + */ + int32 key_family = 1; + + /* + The precise index of the key being identified. + */ + int32 key_index = 2; +} + +message KeyDescriptor { + /* + The raw bytes of the key being identified. + */ + bytes raw_key_bytes = 1; + + /* + The key locator that identifies which key to use for signing. + */ + KeyLocator key_loc = 2; +} + +message DecodeAddrRequest { + string addr = 1; +} + +message ProofFile { + // The raw proof file encoded as bytes. Must be a file and not just an + // individual mint/transfer proof. + bytes raw_proof_file = 1; + + string genesis_point = 2; +} + +message DecodedProof { + // The index depth of the decoded proof, with 0 being the latest proof. + uint32 proof_at_depth = 1; + + // The total number of proofs contained in the decoded proof file (this will + // always be 1 if a single mint/transition proof was given as the raw_proof + // instead of a file). + uint32 number_of_proofs = 2; + + // The asset referenced in the proof. + Asset asset = 3; + + // The reveal meta data associated with the proof, if available. + AssetMeta meta_reveal = 4; + + // The merkle proof for AnchorTx used to prove its + // inclusion within BlockHeader. + bytes tx_merkle_proof = 5; + + // The TaprootProof proving the new inclusion of the + // resulting asset within AnchorTx. + bytes inclusion_proof = 6; + + // The set of TaprootProofs proving the exclusion of + // the resulting asset from all other Taproot outputs within AnchorTx. + repeated bytes exclusion_proofs = 7; + + // An optional TaprootProof needed if this asset is + // the result of a split. SplitRootProof proves inclusion of the root + // asset of the split. + bytes split_root_proof = 8; + + // The number of additional nested full proofs for any inputs found within + // the resulting asset. + uint32 num_additional_inputs = 9; + + // ChallengeWitness is an optional virtual transaction witness that serves + // as an ownership proof for the asset. If this is non-nil, then it is a + // valid transfer witness for a 1-input, 1-output virtual transaction that + // spends the asset in this proof and sends it to the NUMS key, to prove + // that the creator of the proof is able to produce a valid signature to + // spend the asset. + repeated bytes challenge_witness = 10; + + // Indicates whether the state transition this proof represents is a burn, + // meaning that the assets were provably destroyed and can no longer be + // spent. + bool is_burn = 11; + + // GenesisReveal is an optional field that is the Genesis information for + // the asset. This is required for minting proofs. + GenesisReveal genesis_reveal = 12; + + // GroupKeyReveal is an optional field that includes the information needed + // to derive the tweaked group key. + GroupKeyReveal group_key_reveal = 13; +} + +message VerifyProofResponse { + bool valid = 1; + + // The decoded last proof in the file if the proof file was valid. + DecodedProof decoded_proof = 2; +} + +message DecodeProofRequest { + // The raw proof bytes to decode. This can be a full proof file or a single + // mint/transition proof. If it is a full proof file, the proof_at_depth + // field will be used to determine which individual proof within the file to + // decode. + bytes raw_proof = 1; + + // The index depth of the decoded proof, with 0 being the latest proof. This + // is ignored if the raw_proof is a single mint/transition proof and not a + // proof file. + uint32 proof_at_depth = 2; + + // An option to include previous witnesses in decoding. + bool with_prev_witnesses = 3; + + // An option to attempt to retrieve the meta data associated with the proof. + bool with_meta_reveal = 4; +} + +message DecodeProofResponse { + DecodedProof decoded_proof = 1; +} + +message ExportProofRequest { + bytes asset_id = 1; + bytes script_key = 2; + + // TODO(roasbeef): specify information to make new state transition in proof + // file? +} + +enum AddrEventStatus { + ADDR_EVENT_STATUS_UNKNOWN = 0; + ADDR_EVENT_STATUS_TRANSACTION_DETECTED = 1; + ADDR_EVENT_STATUS_TRANSACTION_CONFIRMED = 2; + ADDR_EVENT_STATUS_PROOF_RECEIVED = 3; + ADDR_EVENT_STATUS_COMPLETED = 4; +} + +message AddrEvent { + // The time the event was created in unix timestamp seconds. + uint64 creation_time_unix_seconds = 1; + + // The address the event was created for. + Addr addr = 2; + + // The current status of the event. + AddrEventStatus status = 3; + + // The outpoint that contains the inbound asset transfer. + string outpoint = 4; + + /* + The amount in satoshis that were transferred on chain along with the asset. + This amount is independent of the requested asset amount, which can be + looked up on the address. + */ + uint64 utxo_amt_sat = 5; + + /* + The taproot sibling hash that was used to send to the Taproot output. + */ + bytes taproot_sibling = 6; + + /* + The height at which the on-chain output was confirmed. If this is zero, it + means the output is unconfirmed. + */ + uint32 confirmation_height = 7; + + /* + Indicates whether a proof file can be found for the address' asset ID and + script key. + */ + bool has_proof = 8; +} + +message AddrReceivesRequest { + // Filter receives by a specific address. Leave empty to get all receives. + string filter_addr = 1; + + // Filter receives by a specific status. Leave empty to get all receives. + AddrEventStatus filter_status = 2; +} + +message AddrReceivesResponse { + // The events that match the filter criteria. + repeated AddrEvent events = 1; +} + +message SendAssetRequest { + repeated string tap_addrs = 1; + + // The optional fee rate to use for the minting transaction, in sat/kw. + uint32 fee_rate = 2; + // TODO(roasbeef): maybe in future add details re type of ProofCourier or + // w/e +} + +message PrevInputAsset { + string anchor_point = 1; + bytes asset_id = 2; + bytes script_key = 3; + uint64 amount = 4; +} + +message SendAssetResponse { + AssetTransfer transfer = 1; +} + +message GetInfoRequest { +} + +message GetInfoResponse { + string version = 1; + string lnd_version = 2; + string network = 3; + string lnd_identity_pubkey = 4; + string node_alias = 5; + uint32 block_height = 6; + string block_hash = 7; + bool sync_to_chain = 8; +} + +message SubscribeSendAssetEventNtfnsRequest { +} + +message SendAssetEvent { + oneof event { + // An event which indicates that a send state is about to be executed. + ExecuteSendStateEvent execute_send_state_event = 1; + + // An event which indicates that the proof send backoff wait period will + // start imminently. + ReceiverProofBackoffWaitEvent receiver_proof_backoff_wait_event = 2; + } +} + +message ExecuteSendStateEvent { + // Execute timestamp (microseconds). + int64 timestamp = 1; + + // The send state that is about to be executed. + string send_state = 2; +} + +message ReceiverProofBackoffWaitEvent { + // Transfer attempt timestamp (microseconds). + int64 timestamp = 1; + + // Backoff is the active backoff wait duration. + int64 backoff = 2; + + // Tries counter is the number of tries we've made so far during the + // course of the current backoff procedure to deliver the proof to the + // receiver. + int64 tries_counter = 3; +} + +message FetchAssetMetaRequest { + oneof asset { + // The asset ID of the asset to fetch the meta for. + bytes asset_id = 1; + + // The 32-byte meta hash of the asset meta. + bytes meta_hash = 2; + + // The hex encoded asset ID of the asset to fetch the meta for. + string asset_id_str = 3; + + // The hex encoded meta hash of the asset meta. + string meta_hash_str = 4; + } +} + +message BurnAssetRequest { + oneof asset { + // The asset ID of the asset to burn units of. + bytes asset_id = 1; + + // The hex encoded asset ID of the asset to burn units of. + string asset_id_str = 2; + } + + uint64 amount_to_burn = 3; + + // A safety check to ensure the user is aware of the destructive nature of + // the burn. This needs to be set to the value "assets will be destroyed" + // for the burn to succeed. + string confirmation_text = 4; +} + +message BurnAssetResponse { + // The asset transfer that contains the asset burn as an output. + AssetTransfer burn_transfer = 1; + + // The burn transition proof for the asset burn output. + DecodedProof burn_proof = 2; +} diff --git a/proto/walletrpc/walletkit.proto b/proto/walletrpc/walletkit.proto new file mode 100644 index 000000000..0d3fd9512 --- /dev/null +++ b/proto/walletrpc/walletkit.proto @@ -0,0 +1,1245 @@ +syntax = "proto3"; + +import "lightning.proto"; +import "signrpc/signer.proto"; + +package walletrpc; + +option go_package = "github.com/lightningnetwork/lnd/lnrpc/walletrpc"; + +// WalletKit is a service that gives access to the core functionalities of the +// daemon's wallet. +service WalletKit { + /* + ListUnspent returns a list of all utxos spendable by the wallet with a + number of confirmations between the specified minimum and maximum. By + default, all utxos are listed. To list only the unconfirmed utxos, set + the unconfirmed_only to true. + */ + rpc ListUnspent (ListUnspentRequest) returns (ListUnspentResponse); + + /* + LeaseOutput locks an output to the given ID, preventing it from being + available for any future coin selection attempts. The absolute time of the + lock's expiration is returned. The expiration of the lock can be extended by + successive invocations of this RPC. Outputs can be unlocked before their + expiration through `ReleaseOutput`. + */ + rpc LeaseOutput (LeaseOutputRequest) returns (LeaseOutputResponse); + + /* + ReleaseOutput unlocks an output, allowing it to be available for coin + selection if it remains unspent. The ID should match the one used to + originally lock the output. + */ + rpc ReleaseOutput (ReleaseOutputRequest) returns (ReleaseOutputResponse); + + /* + ListLeases lists all currently locked utxos. + */ + rpc ListLeases (ListLeasesRequest) returns (ListLeasesResponse); + + /* + DeriveNextKey attempts to derive the *next* key within the key family + (account in BIP43) specified. This method should return the next external + child within this branch. + */ + rpc DeriveNextKey (KeyReq) returns (signrpc.KeyDescriptor); + + /* + DeriveKey attempts to derive an arbitrary key specified by the passed + KeyLocator. + */ + rpc DeriveKey (signrpc.KeyLocator) returns (signrpc.KeyDescriptor); + + /* + NextAddr returns the next unused address within the wallet. + */ + rpc NextAddr (AddrRequest) returns (AddrResponse); + + /* + ListAccounts retrieves all accounts belonging to the wallet by default. A + name and key scope filter can be provided to filter through all of the + wallet accounts and return only those matching. + */ + rpc ListAccounts (ListAccountsRequest) returns (ListAccountsResponse); + + /* + RequiredReserve returns the minimum amount of satoshis that should be kept + in the wallet in order to fee bump anchor channels if necessary. The value + scales with the number of public anchor channels but is capped at a maximum. + */ + rpc RequiredReserve (RequiredReserveRequest) + returns (RequiredReserveResponse); + + /* + ListAddresses retrieves all the addresses along with their balance. An + account name filter can be provided to filter through all of the + wallet accounts and return the addresses of only those matching. + */ + rpc ListAddresses (ListAddressesRequest) returns (ListAddressesResponse); + + /* + SignMessageWithAddr returns the compact signature (base64 encoded) created + with the private key of the provided address. This requires the address + to be solely based on a public key lock (no scripts). Obviously the internal + lnd wallet has to possess the private key of the address otherwise + an error is returned. + + This method aims to provide full compatibility with the bitcoin-core and + btcd implementation. Bitcoin-core's algorithm is not specified in a + BIP and only applicable for legacy addresses. This method enhances the + signing for additional address types: P2WKH, NP2WKH, P2TR. + For P2TR addresses this represents a special case. ECDSA is used to create + a compact signature which makes the public key of the signature recoverable. + */ + rpc SignMessageWithAddr (SignMessageWithAddrRequest) + returns (SignMessageWithAddrResponse); + + /* + VerifyMessageWithAddr returns the validity and the recovered public key of + the provided compact signature (base64 encoded). The verification is + twofold. First the validity of the signature itself is checked and then + it is verified that the recovered public key of the signature equals + the public key of the provided address. There is no dependence on the + private key of the address therefore also external addresses are allowed + to verify signatures. + Supported address types are P2PKH, P2WKH, NP2WKH, P2TR. + + This method is the counterpart of the related signing method + (SignMessageWithAddr) and aims to provide full compatibility to + bitcoin-core's implementation. Although bitcoin-core/btcd only provide + this functionality for legacy addresses this function enhances it to + the address types: P2PKH, P2WKH, NP2WKH, P2TR. + + The verification for P2TR addresses is a special case and requires the + ECDSA compact signature to compare the reovered public key to the internal + taproot key. The compact ECDSA signature format was used because there + are still no known compact signature schemes for schnorr signatures. + */ + rpc VerifyMessageWithAddr (VerifyMessageWithAddrRequest) + returns (VerifyMessageWithAddrResponse); + + /* + ImportAccount imports an account backed by an account extended public key. + The master key fingerprint denotes the fingerprint of the root key + corresponding to the account public key (also known as the key with + derivation path m/). This may be required by some hardware wallets for + proper identification and signing. + + The address type can usually be inferred from the key's version, but may be + required for certain keys to map them into the proper scope. + + For BIP-0044 keys, an address type must be specified as we intend to not + support importing BIP-0044 keys into the wallet using the legacy + pay-to-pubkey-hash (P2PKH) scheme. A nested witness address type will force + the standard BIP-0049 derivation scheme, while a witness address type will + force the standard BIP-0084 derivation scheme. + + For BIP-0049 keys, an address type must also be specified to make a + distinction between the standard BIP-0049 address schema (nested witness + pubkeys everywhere) and our own BIP-0049Plus address schema (nested pubkeys + externally, witness pubkeys internally). + + NOTE: Events (deposits/spends) for keys derived from an account will only be + detected by lnd if they happen after the import. Rescans to detect past + events will be supported later on. + */ + rpc ImportAccount (ImportAccountRequest) returns (ImportAccountResponse); + + /* + ImportPublicKey imports a public key as watch-only into the wallet. The + public key is converted into a simple address of the given type and that + address script is watched on chain. For Taproot keys, this will only watch + the BIP-0086 style output script. Use ImportTapscript for more advanced key + spend or script spend outputs. + + NOTE: Events (deposits/spends) for a key will only be detected by lnd if + they happen after the import. Rescans to detect past events will be + supported later on. + */ + rpc ImportPublicKey (ImportPublicKeyRequest) + returns (ImportPublicKeyResponse); + + /* + ImportTapscript imports a Taproot script and internal key and adds the + resulting Taproot output key as a watch-only output script into the wallet. + For BIP-0086 style Taproot keys (no root hash commitment and no script spend + path) use ImportPublicKey. + + NOTE: Events (deposits/spends) for a key will only be detected by lnd if + they happen after the import. Rescans to detect past events will be + supported later on. + + NOTE: Taproot keys imported through this RPC currently _cannot_ be used for + funding PSBTs. Only tracking the balance and UTXOs is currently supported. + */ + rpc ImportTapscript (ImportTapscriptRequest) + returns (ImportTapscriptResponse); + + /* + PublishTransaction attempts to publish the passed transaction to the + network. Once this returns without an error, the wallet will continually + attempt to re-broadcast the transaction on start up, until it enters the + chain. + */ + rpc PublishTransaction (Transaction) returns (PublishResponse); + + /* + SendOutputs is similar to the existing sendmany call in Bitcoind, and + allows the caller to create a transaction that sends to several outputs at + once. This is ideal when wanting to batch create a set of transactions. + */ + rpc SendOutputs (SendOutputsRequest) returns (SendOutputsResponse); + + /* + EstimateFee attempts to query the internal fee estimator of the wallet to + determine the fee (in sat/kw) to attach to a transaction in order to + achieve the confirmation target. + */ + rpc EstimateFee (EstimateFeeRequest) returns (EstimateFeeResponse); + + /* + PendingSweeps returns lists of on-chain outputs that lnd is currently + attempting to sweep within its central batching engine. Outputs with similar + fee rates are batched together in order to sweep them within a single + transaction. + + NOTE: Some of the fields within PendingSweepsRequest are not guaranteed to + remain supported. This is an advanced API that depends on the internals of + the UtxoSweeper, so things may change. + */ + rpc PendingSweeps (PendingSweepsRequest) returns (PendingSweepsResponse); + + /* + BumpFee bumps the fee of an arbitrary input within a transaction. This RPC + takes a different approach than bitcoind's bumpfee command. lnd has a + central batching engine in which inputs with similar fee rates are batched + together to save on transaction fees. Due to this, we cannot rely on + bumping the fee on a specific transaction, since transactions can change at + any point with the addition of new inputs. The list of inputs that + currently exist within lnd's central batching engine can be retrieved + through the PendingSweeps RPC. + + When bumping the fee of an input that currently exists within lnd's central + batching engine, a higher fee transaction will be created that replaces the + lower fee transaction through the Replace-By-Fee (RBF) policy. If it + + This RPC also serves useful when wanting to perform a Child-Pays-For-Parent + (CPFP), where the child transaction pays for its parent's fee. This can be + done by specifying an outpoint within the low fee transaction that is under + the control of the wallet. + + The fee preference can be expressed either as a specific fee rate or a delta + of blocks in which the output should be swept on-chain within. If a fee + preference is not explicitly specified, then an error is returned. + + Note that this RPC currently doesn't perform any validation checks on the + fee preference being provided. For now, the responsibility of ensuring that + the new fee preference is sufficient is delegated to the user. + */ + rpc BumpFee (BumpFeeRequest) returns (BumpFeeResponse); + + /* + ListSweeps returns a list of the sweep transactions our node has produced. + Note that these sweeps may not be confirmed yet, as we record sweeps on + broadcast, not confirmation. + */ + rpc ListSweeps (ListSweepsRequest) returns (ListSweepsResponse); + + /* + LabelTransaction adds a label to a transaction. If the transaction already + has a label the call will fail unless the overwrite bool is set. This will + overwrite the exiting transaction label. Labels must not be empty, and + cannot exceed 500 characters. + */ + rpc LabelTransaction (LabelTransactionRequest) + returns (LabelTransactionResponse); + + /* + FundPsbt creates a fully populated PSBT that contains enough inputs to fund + the outputs specified in the template. There are two ways of specifying a + template: Either by passing in a PSBT with at least one output declared or + by passing in a raw TxTemplate message. + + If there are no inputs specified in the template, coin selection is + performed automatically. If the template does contain any inputs, it is + assumed that full coin selection happened externally and no additional + inputs are added. If the specified inputs aren't enough to fund the outputs + with the given fee rate, an error is returned. + + After either selecting or verifying the inputs, all input UTXOs are locked + with an internal app ID. + + NOTE: If this method returns without an error, it is the caller's + responsibility to either spend the locked UTXOs (by finalizing and then + publishing the transaction) or to unlock/release the locked UTXOs in case of + an error on the caller's side. + */ + rpc FundPsbt (FundPsbtRequest) returns (FundPsbtResponse); + + /* + SignPsbt expects a partial transaction with all inputs and outputs fully + declared and tries to sign all unsigned inputs that have all required fields + (UTXO information, BIP32 derivation information, witness or sig scripts) + set. + If no error is returned, the PSBT is ready to be given to the next signer or + to be finalized if lnd was the last signer. + + NOTE: This RPC only signs inputs (and only those it can sign), it does not + perform any other tasks (such as coin selection, UTXO locking or + input/output/fee value validation, PSBT finalization). Any input that is + incomplete will be skipped. + */ + rpc SignPsbt (SignPsbtRequest) returns (SignPsbtResponse); + + /* + FinalizePsbt expects a partial transaction with all inputs and outputs fully + declared and tries to sign all inputs that belong to the wallet. Lnd must be + the last signer of the transaction. That means, if there are any unsigned + non-witness inputs or inputs without UTXO information attached or inputs + without witness data that do not belong to lnd's wallet, this method will + fail. If no error is returned, the PSBT is ready to be extracted and the + final TX within to be broadcast. + + NOTE: This method does NOT publish the transaction once finalized. It is the + caller's responsibility to either publish the transaction on success or + unlock/release any locked UTXOs in case of an error in this method. + */ + rpc FinalizePsbt (FinalizePsbtRequest) returns (FinalizePsbtResponse); +} + +message ListUnspentRequest { + // The minimum number of confirmations to be included. + int32 min_confs = 1; + + // The maximum number of confirmations to be included. + int32 max_confs = 2; + + // An optional filter to only include outputs belonging to an account. + string account = 3; + + /* + When min_confs and max_confs are zero, setting false implicitly + overrides max_confs to be MaxInt32, otherwise max_confs remains + zero. An error is returned if the value is true and both min_confs + and max_confs are non-zero. (default: false) + */ + bool unconfirmed_only = 4; +} + +message ListUnspentResponse { + // A list of utxos satisfying the specified number of confirmations. + repeated lnrpc.Utxo utxos = 1; +} + +message LeaseOutputRequest { + /* + An ID of 32 random bytes that must be unique for each distinct application + using this RPC which will be used to bound the output lease to. + */ + bytes id = 1; + + // The identifying outpoint of the output being leased. + lnrpc.OutPoint outpoint = 2; + + // The time in seconds before the lock expires. If set to zero, the default + // lock duration is used. + uint64 expiration_seconds = 3; +} + +message LeaseOutputResponse { + /* + The absolute expiration of the output lease represented as a unix timestamp. + */ + uint64 expiration = 1; +} + +message ReleaseOutputRequest { + // The unique ID that was used to lock the output. + bytes id = 1; + + // The identifying outpoint of the output being released. + lnrpc.OutPoint outpoint = 2; +} + +message ReleaseOutputResponse { +} + +message KeyReq { + /* + Is the key finger print of the root pubkey that this request is targeting. + This allows the WalletKit to possibly serve out keys for multiple HD chains + via public derivation. + */ + int32 key_finger_print = 1; + + /* + The target key family to derive a key from. In other contexts, this is + known as the "account". + */ + int32 key_family = 2; +} + +message AddrRequest { + /* + The name of the account to retrieve the next address of. If empty, the + default wallet account is used. + */ + string account = 1; + + /* + The type of address to derive. + */ + AddressType type = 2; + + /* + Whether a change address should be derived. + */ + bool change = 3; +} +message AddrResponse { + /* + The address encoded using a bech32 format. + */ + string addr = 1; +} + +enum AddressType { + UNKNOWN = 0; + WITNESS_PUBKEY_HASH = 1; + NESTED_WITNESS_PUBKEY_HASH = 2; + HYBRID_NESTED_WITNESS_PUBKEY_HASH = 3; + TAPROOT_PUBKEY = 4; +} +message Account { + // The name used to identify the account. + string name = 1; + + // The type of addresses the account supports. + AddressType address_type = 2; + + /* + The public key backing the account that all keys are derived from + represented as an extended key. This will always be empty for the default + imported account in which single public keys are imported into. + */ + string extended_public_key = 3; + + /* + The fingerprint of the root key from which the account public key was + derived from. This will always be zero for the default imported account in + which single public keys are imported into. The bytes are in big-endian + order. + */ + bytes master_key_fingerprint = 4; + + /* + The derivation path corresponding to the account public key. This will + always be empty for the default imported account in which single public keys + are imported into. + */ + string derivation_path = 5; + + /* + The number of keys derived from the external branch of the account public + key. This will always be zero for the default imported account in which + single public keys are imported into. + */ + uint32 external_key_count = 6; + + /* + The number of keys derived from the internal branch of the account public + key. This will always be zero for the default imported account in which + single public keys are imported into. + */ + uint32 internal_key_count = 7; + + // Whether the wallet stores private keys for the account. + bool watch_only = 8; +} + +message AddressProperty { + /* + The address encoded using the appropriate format depending on the + address type (base58, bech32, bech32m). + + Note that lnd's internal/custom keys for channels and other + functionality are derived from the same scope. Since they + aren't really used as addresses and will never have an + on-chain balance, we'll show the public key instead (only if + the show_custom_accounts flag is provided). + */ + string address = 1; + + // Denotes if the address is a change address. + bool is_internal = 2; + + // The balance of the address. + int64 balance = 3; +} + +message AccountWithAddresses { + // The name used to identify the account. + string name = 1; + + // The type of addresses the account supports. + AddressType address_type = 2; + + /* + The derivation path corresponding to the account public key. This will + always be empty for the default imported account in which single public keys + are imported into. + */ + string derivation_path = 3; + + /* + List of address, its type internal/external & balance. + Note that the order of addresses will be random and not according to the + derivation index, since that information is not stored by the underlying + wallet. + */ + repeated AddressProperty addresses = 4; +} + +message ListAccountsRequest { + // An optional filter to only return accounts matching this name. + string name = 1; + + // An optional filter to only return accounts matching this address type. + AddressType address_type = 2; +} + +message ListAccountsResponse { + repeated Account accounts = 1; +} + +message RequiredReserveRequest { + // The number of additional channels the user would like to open. + uint32 additional_public_channels = 1; +} + +message RequiredReserveResponse { + // The amount of reserve required. + int64 required_reserve = 1; +} + +message ListAddressesRequest { + // An optional filter to only return addresses matching this account. + string account_name = 1; + + // An optional flag to return LND's custom accounts (Purpose=1017) + // public key along with other addresses. + bool show_custom_accounts = 2; +} + +message ListAddressesResponse { + // A list of all the accounts and their addresses. + repeated AccountWithAddresses account_with_addresses = 1; +} + +message SignMessageWithAddrRequest { + // The message to be signed. When using REST, this field must be encoded as + // base64. + bytes msg = 1; + + // The address which will be used to look up the private key and sign the + // corresponding message. + string addr = 2; +} + +message SignMessageWithAddrResponse { + // The compact ECDSA signature for the given message encoded in base64. + string signature = 1; +} + +message VerifyMessageWithAddrRequest { + // The message to be signed. When using REST, this field must be encoded as + // base64. + bytes msg = 1; + + // The compact ECDSA signature to be verified over the given message + // ecoded in base64. + string signature = 2; + + // The address which will be used to look up the public key and verify the + // the signature. + string addr = 3; +} + +message VerifyMessageWithAddrResponse { + // Whether the signature was valid over the given message. + bool valid = 1; + + // The pubkey recovered from the signature. + bytes pubkey = 2; +} + +message ImportAccountRequest { + // A name to identify the account with. + string name = 1; + + /* + A public key that corresponds to a wallet account represented as an extended + key. It must conform to a derivation path of the form + m/purpose'/coin_type'/account'. + */ + string extended_public_key = 2; + + /* + The fingerprint of the root key (also known as the key with derivation path + m/) from which the account public key was derived from. This may be required + by some hardware wallets for proper identification and signing. The bytes + must be in big-endian order. + */ + bytes master_key_fingerprint = 3; + + /* + An address type is only required when the extended account public key has a + legacy version (xpub, tpub, etc.), such that the wallet cannot detect what + address scheme it belongs to. + */ + AddressType address_type = 4; + + /* + Whether a dry run should be attempted when importing the account. This + serves as a way to confirm whether the account is being imported correctly + by returning the first N addresses for the external and internal branches of + the account. If these addresses match as expected, then it should be safe to + import the account as is. + */ + bool dry_run = 5; +} +message ImportAccountResponse { + // The details of the imported account. + Account account = 1; + + /* + The first N addresses that belong to the external branch of the account. + The external branch is typically used for external non-change addresses. + These are only returned if a dry run was specified within the request. + */ + repeated string dry_run_external_addrs = 2; + + /* + The first N addresses that belong to the internal branch of the account. + The internal branch is typically used for change addresses. These are only + returned if a dry run was specified within the request. + */ + repeated string dry_run_internal_addrs = 3; +} + +message ImportPublicKeyRequest { + // A compressed public key represented as raw bytes. + bytes public_key = 1; + + // The type of address that will be generated from the public key. + AddressType address_type = 2; +} +message ImportPublicKeyResponse { +} + +message ImportTapscriptRequest { + /* + The internal public key, serialized as 32-byte x-only public key. + */ + bytes internal_public_key = 1; + + oneof script { + /* + The full script tree with all individual leaves is known and the root + hash can be constructed from the full tree directly. + */ + TapscriptFullTree full_tree = 2; + + /* + Only a single script leaf is known. To construct the root hash, the full + inclusion proof must also be provided. + */ + TapscriptPartialReveal partial_reveal = 3; + + /* + Only the root hash of the Taproot script tree (or other form of Taproot + commitment) is known. + */ + bytes root_hash_only = 4; + + /* + Only the final, tweaked Taproot key is known and no additional + information about the internal key or type of tweak that was used to + derive it. When this is set, the wallet treats the key in + internal_public_key as the Taproot key directly. This can be useful for + tracking arbitrary Taproot outputs without the goal of ever being able + to spend from them through the internal wallet. + */ + bool full_key_only = 5; + } +} + +message TapscriptFullTree { + /* + The complete, ordered list of all tap leaves of the tree. + */ + repeated TapLeaf all_leaves = 1; +} + +message TapLeaf { + // The leaf version. Should be 0xc0 (192) in case of a SegWit v1 script. + uint32 leaf_version = 1; + + // The script of the tap leaf. + bytes script = 2; +} + +message TapscriptPartialReveal { + // The tap leaf that is known and will be revealed. + TapLeaf revealed_leaf = 1; + + // The BIP-0341 serialized inclusion proof that is required to prove that + // the revealed leaf is part of the tree. This contains 0..n blocks of 32 + // bytes. If the tree only contained a single leaf (which is the revealed + // leaf), this can be empty. + bytes full_inclusion_proof = 2; +} + +message ImportTapscriptResponse { + /* + The resulting pay-to-Taproot address that represents the imported internal + key with the script committed to it. + */ + string p2tr_address = 1; +} + +message Transaction { + /* + The raw serialized transaction. Despite the field name, this does need to be + specified in raw bytes (or base64 encoded when using REST) and not in hex. + To not break existing software, the field can't simply be renamed. + */ + bytes tx_hex = 1; + + /* + An optional label to save with the transaction. Limited to 500 characters. + */ + string label = 2; +} +message PublishResponse { + /* + If blank, then no error occurred and the transaction was successfully + published. If not the empty string, then a string representation of the + broadcast error. + + TODO(roasbeef): map to a proper enum type + */ + string publish_error = 1; +} + +message SendOutputsRequest { + /* + The number of satoshis per kilo weight that should be used when crafting + this transaction. + */ + int64 sat_per_kw = 1; + + /* + A slice of the outputs that should be created in the transaction produced. + */ + repeated signrpc.TxOut outputs = 2; + + // An optional label for the transaction, limited to 500 characters. + string label = 3; + + // The minimum number of confirmations each one of your outputs used for + // the transaction must satisfy. + int32 min_confs = 4; + + // Whether unconfirmed outputs should be used as inputs for the transaction. + bool spend_unconfirmed = 5; +} +message SendOutputsResponse { + /* + The serialized transaction sent out on the network. + */ + bytes raw_tx = 1; +} + +message EstimateFeeRequest { + /* + The number of confirmations to shoot for when estimating the fee. + */ + int32 conf_target = 1; +} +message EstimateFeeResponse { + /* + The amount of satoshis per kw that should be used in order to reach the + confirmation target in the request. + */ + int64 sat_per_kw = 1; +} + +enum WitnessType { + UNKNOWN_WITNESS = 0; + + /* + A witness that allows us to spend the output of a commitment transaction + after a relative lock-time lockout. + */ + COMMITMENT_TIME_LOCK = 1; + + /* + A witness that allows us to spend a settled no-delay output immediately on a + counterparty's commitment transaction. + */ + COMMITMENT_NO_DELAY = 2; + + /* + A witness that allows us to sweep the settled output of a malicious + counterparty's who broadcasts a revoked commitment transaction. + */ + COMMITMENT_REVOKE = 3; + + /* + A witness that allows us to sweep an HTLC which we offered to the remote + party in the case that they broadcast a revoked commitment state. + */ + HTLC_OFFERED_REVOKE = 4; + + /* + A witness that allows us to sweep an HTLC output sent to us in the case that + the remote party broadcasts a revoked commitment state. + */ + HTLC_ACCEPTED_REVOKE = 5; + + /* + A witness that allows us to sweep an HTLC output that we extended to a + party, but was never fulfilled. This HTLC output isn't directly on the + commitment transaction, but is the result of a confirmed second-level HTLC + transaction. As a result, we can only spend this after a CSV delay. + */ + HTLC_OFFERED_TIMEOUT_SECOND_LEVEL = 6; + + /* + A witness that allows us to sweep an HTLC output that was offered to us, and + for which we have a payment preimage. This HTLC output isn't directly on our + commitment transaction, but is the result of confirmed second-level HTLC + transaction. As a result, we can only spend this after a CSV delay. + */ + HTLC_ACCEPTED_SUCCESS_SECOND_LEVEL = 7; + + /* + A witness that allows us to sweep an HTLC that we offered to the remote + party which lies in the commitment transaction of the remote party. We can + spend this output after the absolute CLTV timeout of the HTLC as passed. + */ + HTLC_OFFERED_REMOTE_TIMEOUT = 8; + + /* + A witness that allows us to sweep an HTLC that was offered to us by the + remote party. We use this witness in the case that the remote party goes to + chain, and we know the pre-image to the HTLC. We can sweep this without any + additional timeout. + */ + HTLC_ACCEPTED_REMOTE_SUCCESS = 9; + + /* + A witness that allows us to sweep an HTLC from the remote party's commitment + transaction in the case that the broadcast a revoked commitment, but then + also immediately attempt to go to the second level to claim the HTLC. + */ + HTLC_SECOND_LEVEL_REVOKE = 10; + + /* + A witness type that allows us to spend a regular p2wkh output that's sent to + an output which is under complete control of the backing wallet. + */ + WITNESS_KEY_HASH = 11; + + /* + A witness type that allows us to sweep an output that sends to a nested P2SH + script that pays to a key solely under our control. + */ + NESTED_WITNESS_KEY_HASH = 12; + + /* + A witness type that allows us to spend our anchor on the commitment + transaction. + */ + COMMITMENT_ANCHOR = 13; + + /* + A witness type that is similar to the COMMITMENT_NO_DELAY type, + but it omits the tweak that randomizes the key we need to + spend with a channel peer supplied set of randomness. + */ + COMMITMENT_NO_DELAY_TWEAKLESS = 14; + + /* + A witness type that allows us to spend our output on the counterparty's + commitment transaction after a confirmation. + */ + COMMITMENT_TO_REMOTE_CONFIRMED = 15; + + /* + A witness type that allows us to sweep an HTLC output that we extended + to a party, but was never fulfilled. This _is_ the HTLC output directly + on our commitment transaction, and the input to the second-level HTLC + timeout transaction. It can only be spent after CLTV expiry, and + commitment confirmation. + */ + HTLC_OFFERED_TIMEOUT_SECOND_LEVEL_INPUT_CONFIRMED = 16; + + /* + A witness type that allows us to sweep an HTLC output that was offered + to us, and for which we have a payment preimage. This _is_ the HTLC + output directly on our commitment transaction, and the input to the + second-level HTLC success transaction. It can only be spent after the + commitment has confirmed. + */ + HTLC_ACCEPTED_SUCCESS_SECOND_LEVEL_INPUT_CONFIRMED = 17; + + /* + A witness type that allows us to spend our output on our local + commitment transaction after a relative and absolute lock-time lockout as + part of the script enforced lease commitment type. + */ + LEASE_COMMITMENT_TIME_LOCK = 18; + + /* + A witness type that allows us to spend our output on the counterparty's + commitment transaction after a confirmation and absolute locktime as part + of the script enforced lease commitment type. + */ + LEASE_COMMITMENT_TO_REMOTE_CONFIRMED = 19; + + /* + A witness type that allows us to sweep an HTLC output that we extended + to a party, but was never fulfilled. This HTLC output isn't directly on + the commitment transaction, but is the result of a confirmed second-level + HTLC transaction. As a result, we can only spend this after a CSV delay + and CLTV locktime as part of the script enforced lease commitment type. + */ + LEASE_HTLC_OFFERED_TIMEOUT_SECOND_LEVEL = 20; + + /* + A witness type that allows us to sweep an HTLC output that was offered + to us, and for which we have a payment preimage. This HTLC output isn't + directly on our commitment transaction, but is the result of confirmed + second-level HTLC transaction. As a result, we can only spend this after + a CSV delay and CLTV locktime as part of the script enforced lease + commitment type. + */ + LEASE_HTLC_ACCEPTED_SUCCESS_SECOND_LEVEL = 21; + + /* + A witness type that allows us to spend a regular p2tr output that's sent + to an output which is under complete control of the backing wallet. + */ + TAPROOT_PUB_KEY_SPEND = 22; +} + +message PendingSweep { + // The outpoint of the output we're attempting to sweep. + lnrpc.OutPoint outpoint = 1; + + // The witness type of the output we're attempting to sweep. + WitnessType witness_type = 2; + + // The value of the output we're attempting to sweep. + uint32 amount_sat = 3; + + /* + Deprecated, use sat_per_vbyte. + The fee rate we'll use to sweep the output, expressed in sat/vbyte. The fee + rate is only determined once a sweeping transaction for the output is + created, so it's possible for this to be 0 before this. + */ + uint32 sat_per_byte = 4 [deprecated = true]; + + // The number of broadcast attempts we've made to sweep the output. + uint32 broadcast_attempts = 5; + + /* + The next height of the chain at which we'll attempt to broadcast the + sweep transaction of the output. + */ + uint32 next_broadcast_height = 6; + + // The requested confirmation target for this output. + uint32 requested_conf_target = 8; + + // Deprecated, use requested_sat_per_vbyte. + // The requested fee rate, expressed in sat/vbyte, for this output. + uint32 requested_sat_per_byte = 9 [deprecated = true]; + + /* + The fee rate we'll use to sweep the output, expressed in sat/vbyte. The fee + rate is only determined once a sweeping transaction for the output is + created, so it's possible for this to be 0 before this. + */ + uint64 sat_per_vbyte = 10; + + // The requested fee rate, expressed in sat/vbyte, for this output. + uint64 requested_sat_per_vbyte = 11; + + /* + Whether this input must be force-swept. This means that it is swept even + if it has a negative yield. + */ + bool force = 7; +} + +message PendingSweepsRequest { +} + +message PendingSweepsResponse { + /* + The set of outputs currently being swept by lnd's central batching engine. + */ + repeated PendingSweep pending_sweeps = 1; +} + +message BumpFeeRequest { + // The input we're attempting to bump the fee of. + lnrpc.OutPoint outpoint = 1; + + // The target number of blocks that the input should be spent within. + uint32 target_conf = 2; + + /* + Deprecated, use sat_per_vbyte. + The fee rate, expressed in sat/vbyte, that should be used to spend the input + with. + */ + uint32 sat_per_byte = 3 [deprecated = true]; + + /* + Whether this input must be force-swept. This means that it is swept even + if it has a negative yield. + */ + bool force = 4; + + /* + The fee rate, expressed in sat/vbyte, that should be used to spend the input + with. + */ + uint64 sat_per_vbyte = 5; +} + +message BumpFeeResponse { +} + +message ListSweepsRequest { + /* + Retrieve the full sweep transaction details. If false, only the sweep txids + will be returned. Note that some sweeps that LND publishes will have been + replaced-by-fee, so will not be included in this output. + */ + bool verbose = 1; +} + +message ListSweepsResponse { + message TransactionIDs { + /* + Reversed, hex-encoded string representing the transaction ids of the + sweeps that our node has broadcast. Note that these transactions may + not have confirmed yet, we record sweeps on broadcast, not confirmation. + */ + repeated string transaction_ids = 1; + } + + oneof sweeps { + lnrpc.TransactionDetails transaction_details = 1; + TransactionIDs transaction_ids = 2; + } +} + +message LabelTransactionRequest { + // The txid of the transaction to label. Note: When using gRPC, the bytes + // must be in little-endian (reverse) order. + bytes txid = 1; + + // The label to add to the transaction, limited to 500 characters. + string label = 2; + + // Whether to overwrite the existing label, if it is present. + bool overwrite = 3; +} + +message LabelTransactionResponse { +} + +// The possible change address types for default accounts and single imported +// public keys. By default, P2WPKH will be used. We don't provide the +// possibility to choose P2PKH as it is a legacy key scope, nor NP2WPKH as +// no key scope permits to do so. For custom accounts, no change type should +// be provided as the coin selection key scope will always be used to generate +// the change address. +enum ChangeAddressType { + // CHANGE_ADDRESS_TYPE_UNSPECIFIED indicates that no change address type is + // provided. We will then use P2WPKH address type for change (BIP0084 key + // scope). + CHANGE_ADDRESS_TYPE_UNSPECIFIED = 0; + + // CHANGE_ADDRESS_TYPE_P2TR indicates to use P2TR address for change output + // (BIP0086 key scope). + CHANGE_ADDRESS_TYPE_P2TR = 1; +} + +message FundPsbtRequest { + oneof template { + /* + Use an existing PSBT packet as the template for the funded PSBT. + + The packet must contain at least one non-dust output. If one or more + inputs are specified, no coin selection is performed. In that case every + input must be an UTXO known to the wallet that has not been locked + before. The sum of all inputs must be sufficiently greater than the sum + of all outputs to pay a miner fee with the specified fee rate. A change + output is added to the PSBT if necessary. + */ + bytes psbt = 1; + + /* + Use the outputs and optional inputs from this raw template. + */ + TxTemplate raw = 2; + } + + oneof fees { + /* + The target number of blocks that the transaction should be confirmed in. + */ + uint32 target_conf = 3; + + /* + The fee rate, expressed in sat/vbyte, that should be used to spend the + input with. + */ + uint64 sat_per_vbyte = 4; + } + + /* + The name of the account to fund the PSBT with. If empty, the default wallet + account is used. + */ + string account = 5; + + // The minimum number of confirmations each one of your outputs used for + // the transaction must satisfy. + int32 min_confs = 6; + + // Whether unconfirmed outputs should be used as inputs for the transaction. + bool spend_unconfirmed = 7; + + // The address type for the change. If empty, P2WPKH addresses will be used + // for default accounts and single imported public keys. For custom + // accounts, no change type should be provided as the coin selection key + // scope will always be used to generate the change address. + ChangeAddressType change_type = 8; +} +message FundPsbtResponse { + /* + The funded but not yet signed PSBT packet. + */ + bytes funded_psbt = 1; + + /* + The index of the added change output or -1 if no change was left over. + */ + int32 change_output_index = 2; + + /* + The list of lock leases that were acquired for the inputs in the funded PSBT + packet. + */ + repeated UtxoLease locked_utxos = 3; +} + +message TxTemplate { + /* + An optional list of inputs to use. Every input must be an UTXO known to the + wallet that has not been locked before. The sum of all inputs must be + sufficiently greater than the sum of all outputs to pay a miner fee with the + fee rate specified in the parent message. + + If no inputs are specified, coin selection will be performed instead and + inputs of sufficient value will be added to the resulting PSBT. + */ + repeated lnrpc.OutPoint inputs = 1; + + /* + A map of all addresses and the amounts to send to in the funded PSBT. + */ + map outputs = 2; +} + +message UtxoLease { + /* + A 32 byte random ID that identifies the lease. + */ + bytes id = 1; + + // The identifying outpoint of the output being leased. + lnrpc.OutPoint outpoint = 2; + + /* + The absolute expiration of the output lease represented as a unix timestamp. + */ + uint64 expiration = 3; + + /* + The public key script of the leased output. + */ + bytes pk_script = 4; + + /* + The value of the leased output in satoshis. + */ + uint64 value = 5; +} + +message SignPsbtRequest { + /* + The PSBT that should be signed. The PSBT must contain all required inputs, + outputs, UTXO data and custom fields required to identify the signing key. + */ + bytes funded_psbt = 1; +} + +message SignPsbtResponse { + // The signed transaction in PSBT format. + bytes signed_psbt = 1; + + // The indices of signed inputs. + repeated uint32 signed_inputs = 2; +} + +message FinalizePsbtRequest { + /* + A PSBT that should be signed and finalized. The PSBT must contain all + required inputs, outputs, UTXO data and partial signatures of all other + signers. + */ + bytes funded_psbt = 1; + + /* + The name of the account to finalize the PSBT with. If empty, the default + wallet account is used. + */ + string account = 5; +} +message FinalizePsbtResponse { + // The fully signed and finalized transaction in PSBT format. + bytes signed_psbt = 1; + + // The fully signed and finalized transaction in the raw wire format. + bytes raw_final_tx = 2; +} + +message ListLeasesRequest { +} + +message ListLeasesResponse { + // The list of currently leased utxos. + repeated UtxoLease locked_utxos = 1; +} diff --git a/proto/walletunlocker.proto b/proto/walletunlocker.proto new file mode 100644 index 000000000..faf3c0892 --- /dev/null +++ b/proto/walletunlocker.proto @@ -0,0 +1,338 @@ +syntax = "proto3"; + +import "lightning.proto"; + +package lnrpc; + +option go_package = "github.com/lightningnetwork/lnd/lnrpc"; + +/* + * Comments in this file will be directly parsed into the API + * Documentation as descriptions of the associated method, message, or field. + * These descriptions should go right above the definition of the object, and + * can be in either block or // comment format. + * + * An RPC method can be matched to an lncli command by placing a line in the + * beginning of the description in exactly the following format: + * lncli: `methodname` + * + * Failure to specify the exact name of the command will cause documentation + * generation to fail. + * + * More information on how exactly the gRPC documentation is generated from + * this proto file can be found here: + * https://github.com/lightninglabs/lightning-api + */ + +// WalletUnlocker is a service that is used to set up a wallet password for +// lnd at first startup, and unlock a previously set up wallet. +service WalletUnlocker { + /* + GenSeed is the first method that should be used to instantiate a new lnd + instance. This method allows a caller to generate a new aezeed cipher seed + given an optional passphrase. If provided, the passphrase will be necessary + to decrypt the cipherseed to expose the internal wallet seed. + + Once the cipherseed is obtained and verified by the user, the InitWallet + method should be used to commit the newly generated seed, and create the + wallet. + */ + rpc GenSeed (GenSeedRequest) returns (GenSeedResponse); + + /* + InitWallet is used when lnd is starting up for the first time to fully + initialize the daemon and its internal wallet. At the very least a wallet + password must be provided. This will be used to encrypt sensitive material + on disk. + + In the case of a recovery scenario, the user can also specify their aezeed + mnemonic and passphrase. If set, then the daemon will use this prior state + to initialize its internal wallet. + + Alternatively, this can be used along with the GenSeed RPC to obtain a + seed, then present it to the user. Once it has been verified by the user, + the seed can be fed into this RPC in order to commit the new wallet. + */ + rpc InitWallet (InitWalletRequest) returns (InitWalletResponse); + + /* lncli: `unlock` + UnlockWallet is used at startup of lnd to provide a password to unlock + the wallet database. + */ + rpc UnlockWallet (UnlockWalletRequest) returns (UnlockWalletResponse); + + /* lncli: `changepassword` + ChangePassword changes the password of the encrypted wallet. This will + automatically unlock the wallet database if successful. + */ + rpc ChangePassword (ChangePasswordRequest) returns (ChangePasswordResponse); +} + +message GenSeedRequest { + /* + aezeed_passphrase is an optional user provided passphrase that will be used + to encrypt the generated aezeed cipher seed. When using REST, this field + must be encoded as base64. + */ + bytes aezeed_passphrase = 1; + + /* + seed_entropy is an optional 16-bytes generated via CSPRNG. If not + specified, then a fresh set of randomness will be used to create the seed. + When using REST, this field must be encoded as base64. + */ + bytes seed_entropy = 2; +} +message GenSeedResponse { + /* + cipher_seed_mnemonic is a 24-word mnemonic that encodes a prior aezeed + cipher seed obtained by the user. This field is optional, as if not + provided, then the daemon will generate a new cipher seed for the user. + Otherwise, then the daemon will attempt to recover the wallet state linked + to this cipher seed. + */ + repeated string cipher_seed_mnemonic = 1; + + /* + enciphered_seed are the raw aezeed cipher seed bytes. This is the raw + cipher text before run through our mnemonic encoding scheme. + */ + bytes enciphered_seed = 2; +} + +message InitWalletRequest { + /* + wallet_password is the passphrase that should be used to encrypt the + wallet. This MUST be at least 8 chars in length. After creation, this + password is required to unlock the daemon. When using REST, this field + must be encoded as base64. + */ + bytes wallet_password = 1; + + /* + cipher_seed_mnemonic is a 24-word mnemonic that encodes a prior aezeed + cipher seed obtained by the user. This may have been generated by the + GenSeed method, or be an existing seed. + */ + repeated string cipher_seed_mnemonic = 2; + + /* + aezeed_passphrase is an optional user provided passphrase that will be used + to encrypt the generated aezeed cipher seed. When using REST, this field + must be encoded as base64. + */ + bytes aezeed_passphrase = 3; + + /* + recovery_window is an optional argument specifying the address lookahead + when restoring a wallet seed. The recovery window applies to each + individual branch of the BIP44 derivation paths. Supplying a recovery + window of zero indicates that no addresses should be recovered, such after + the first initialization of the wallet. + */ + int32 recovery_window = 4; + + /* + channel_backups is an optional argument that allows clients to recover the + settled funds within a set of channels. This should be populated if the + user was unable to close out all channels and sweep funds before partial or + total data loss occurred. If specified, then after on-chain recovery of + funds, lnd begin to carry out the data loss recovery protocol in order to + recover the funds in each channel from a remote force closed transaction. + */ + ChanBackupSnapshot channel_backups = 5; + + /* + stateless_init is an optional argument instructing the daemon NOT to create + any *.macaroon files in its filesystem. If this parameter is set, then the + admin macaroon returned in the response MUST be stored by the caller of the + RPC as otherwise all access to the daemon will be lost! + */ + bool stateless_init = 6; + + /* + extended_master_key is an alternative to specifying cipher_seed_mnemonic and + aezeed_passphrase. Instead of deriving the master root key from the entropy + of an aezeed cipher seed, the given extended master root key is used + directly as the wallet's master key. This allows users to import/use a + master key from another wallet. When doing so, lnd still uses its default + SegWit only (BIP49/84) derivation paths and funds from custom/non-default + derivation paths will not automatically appear in the on-chain wallet. Using + an 'xprv' instead of an aezeed also has the disadvantage that the wallet's + birthday is not known as that is an information that's only encoded in the + aezeed, not the xprv. Therefore a birthday needs to be specified in + extended_master_key_birthday_timestamp or a "safe" default value will be + used. + */ + string extended_master_key = 7; + + /* + extended_master_key_birthday_timestamp is the optional unix timestamp in + seconds to use as the wallet's birthday when using an extended master key + to restore the wallet. lnd will only start scanning for funds in blocks that + are after the birthday which can speed up the process significantly. If the + birthday is not known, this should be left at its default value of 0 in + which case lnd will start scanning from the first SegWit block (481824 on + mainnet). + */ + uint64 extended_master_key_birthday_timestamp = 8; + + /* + watch_only is the third option of initializing a wallet: by importing + account xpubs only and therefore creating a watch-only wallet that does not + contain any private keys. That means the wallet won't be able to sign for + any of the keys and _needs_ to be run with a remote signer that has the + corresponding private keys and can serve signing RPC requests. + */ + WatchOnly watch_only = 9; + + /* + macaroon_root_key is an optional 32 byte macaroon root key that can be + provided when initializing the wallet rather than letting lnd generate one + on its own. + */ + bytes macaroon_root_key = 10; +} +message InitWalletResponse { + /* + The binary serialized admin macaroon that can be used to access the daemon + after creating the wallet. If the stateless_init parameter was set to true, + this is the ONLY copy of the macaroon and MUST be stored safely by the + caller. Otherwise a copy of this macaroon is also persisted on disk by the + daemon, together with other macaroon files. + */ + bytes admin_macaroon = 1; +} + +message WatchOnly { + /* + The unix timestamp in seconds of when the master key was created. lnd will + only start scanning for funds in blocks that are after the birthday which + can speed up the process significantly. If the birthday is not known, this + should be left at its default value of 0 in which case lnd will start + scanning from the first SegWit block (481824 on mainnet). + */ + uint64 master_key_birthday_timestamp = 1; + + /* + The fingerprint of the root key (also known as the key with derivation path + m/) from which the account public keys were derived from. This may be + required by some hardware wallets for proper identification and signing. The + bytes must be in big-endian order. + */ + bytes master_key_fingerprint = 2; + + /* + The list of accounts to import. There _must_ be an account for all of lnd's + main key scopes: BIP49/BIP84 (m/49'/0'/0', m/84'/0'/0', note that the + coin type is always 0, even for testnet/regtest) and lnd's internal key + scope (m/1017'/'/'), where account is the key family as + defined in `keychain/derivation.go` (currently indices 0 to 9). + */ + repeated WatchOnlyAccount accounts = 3; +} + +message WatchOnlyAccount { + /* + Purpose is the first number in the derivation path, must be either 49, 84 + or 1017. + */ + uint32 purpose = 1; + + /* + Coin type is the second number in the derivation path, this is _always_ 0 + for purposes 49 and 84. It only needs to be set to 1 for purpose 1017 on + testnet or regtest. + */ + uint32 coin_type = 2; + + /* + Account is the third number in the derivation path. For purposes 49 and 84 + at least the default account (index 0) needs to be created but optional + additional accounts are allowed. For purpose 1017 there needs to be exactly + one account for each of the key families defined in `keychain/derivation.go` + (currently indices 0 to 9) + */ + uint32 account = 3; + + /* + The extended public key at depth 3 for the given account. + */ + string xpub = 4; +} + +message UnlockWalletRequest { + /* + wallet_password should be the current valid passphrase for the daemon. This + will be required to decrypt on-disk material that the daemon requires to + function properly. When using REST, this field must be encoded as base64. + */ + bytes wallet_password = 1; + + /* + recovery_window is an optional argument specifying the address lookahead + when restoring a wallet seed. The recovery window applies to each + individual branch of the BIP44 derivation paths. Supplying a recovery + window of zero indicates that no addresses should be recovered, such after + the first initialization of the wallet. + */ + int32 recovery_window = 2; + + /* + channel_backups is an optional argument that allows clients to recover the + settled funds within a set of channels. This should be populated if the + user was unable to close out all channels and sweep funds before partial or + total data loss occurred. If specified, then after on-chain recovery of + funds, lnd begin to carry out the data loss recovery protocol in order to + recover the funds in each channel from a remote force closed transaction. + */ + ChanBackupSnapshot channel_backups = 3; + + /* + stateless_init is an optional argument instructing the daemon NOT to create + any *.macaroon files in its file system. + */ + bool stateless_init = 4; +} +message UnlockWalletResponse { +} + +message ChangePasswordRequest { + /* + current_password should be the current valid passphrase used to unlock the + daemon. When using REST, this field must be encoded as base64. + */ + bytes current_password = 1; + + /* + new_password should be the new passphrase that will be needed to unlock the + daemon. When using REST, this field must be encoded as base64. + */ + bytes new_password = 2; + + /* + stateless_init is an optional argument instructing the daemon NOT to create + any *.macaroon files in its filesystem. If this parameter is set, then the + admin macaroon returned in the response MUST be stored by the caller of the + RPC as otherwise all access to the daemon will be lost! + */ + bool stateless_init = 3; + + /* + new_macaroon_root_key is an optional argument instructing the daemon to + rotate the macaroon root key when set to true. This will invalidate all + previously generated macaroons. + */ + bool new_macaroon_root_key = 4; +} +message ChangePasswordResponse { + /* + The binary serialized admin macaroon that can be used to access the daemon + after rotating the macaroon root key. If both the stateless_init and + new_macaroon_root_key parameter were set to true, this is the ONLY copy of + the macaroon that was created from the new root key and MUST be stored + safely by the caller. Otherwise a copy of this macaroon is also persisted on + disk by the daemon, together with other macaroon files. + */ + bytes admin_macaroon = 1; +} diff --git a/proto/watchtowerrpc/watchtower.proto b/proto/watchtowerrpc/watchtower.proto new file mode 100644 index 000000000..f3be62163 --- /dev/null +++ b/proto/watchtowerrpc/watchtower.proto @@ -0,0 +1,30 @@ +syntax = "proto3"; + +package watchtowerrpc; + +option go_package = "github.com/lightningnetwork/lnd/lnrpc/watchtowerrpc"; + +// Watchtower is a service that grants access to the watchtower server +// functionality of the daemon. +service Watchtower { + /* lncli: tower info + GetInfo returns general information concerning the companion watchtower + including its public key and URIs where the server is currently + listening for clients. + */ + rpc GetInfo (GetInfoRequest) returns (GetInfoResponse); +} + +message GetInfoRequest { +} + +message GetInfoResponse { + // The public key of the watchtower. + bytes pubkey = 1; + + // The listening addresses of the watchtower. + repeated string listeners = 2; + + // The URIs of the watchtower. + repeated string uris = 3; +} diff --git a/proto/wtclientrpc/wtclient.proto b/proto/wtclientrpc/wtclient.proto new file mode 100644 index 000000000..413f61afa --- /dev/null +++ b/proto/wtclientrpc/wtclient.proto @@ -0,0 +1,224 @@ +syntax = "proto3"; + +package wtclientrpc; + +option go_package = "github.com/lightningnetwork/lnd/lnrpc/wtclientrpc"; + +// WatchtowerClient is a service that grants access to the watchtower client +// functionality of the daemon. +service WatchtowerClient { + /* + AddTower adds a new watchtower reachable at the given address and + considers it for new sessions. If the watchtower already exists, then + any new addresses included will be considered when dialing it for + session negotiations and backups. + */ + rpc AddTower (AddTowerRequest) returns (AddTowerResponse); + + /* + RemoveTower removes a watchtower from being considered for future session + negotiations and from being used for any subsequent backups until it's added + again. If an address is provided, then this RPC only serves as a way of + removing the address from the watchtower instead. + */ + rpc RemoveTower (RemoveTowerRequest) returns (RemoveTowerResponse); + + // ListTowers returns the list of watchtowers registered with the client. + rpc ListTowers (ListTowersRequest) returns (ListTowersResponse); + + // GetTowerInfo retrieves information for a registered watchtower. + rpc GetTowerInfo (GetTowerInfoRequest) returns (Tower); + + // Stats returns the in-memory statistics of the client since startup. + rpc Stats (StatsRequest) returns (StatsResponse); + + // Policy returns the active watchtower client policy configuration. + rpc Policy (PolicyRequest) returns (PolicyResponse); +} + +message AddTowerRequest { + // The identifying public key of the watchtower to add. + bytes pubkey = 1; + + // A network address the watchtower is reachable over. + string address = 2; +} + +message AddTowerResponse { +} + +message RemoveTowerRequest { + // The identifying public key of the watchtower to remove. + bytes pubkey = 1; + + /* + If set, then the record for this address will be removed, indicating that is + is stale. Otherwise, the watchtower will no longer be used for future + session negotiations and backups. + */ + string address = 2; +} + +message RemoveTowerResponse { +} + +message GetTowerInfoRequest { + // The identifying public key of the watchtower to retrieve information for. + bytes pubkey = 1; + + // Whether we should include sessions with the watchtower in the response. + bool include_sessions = 2; + + // Whether to exclude exhausted sessions in the response info. This option + // is only meaningful if include_sessions is true. + bool exclude_exhausted_sessions = 3; +} + +message TowerSession { + /* + The total number of successful backups that have been made to the + watchtower session. + */ + uint32 num_backups = 1; + + /* + The total number of backups in the session that are currently pending to be + acknowledged by the watchtower. + */ + uint32 num_pending_backups = 2; + + // The maximum number of backups allowed by the watchtower session. + uint32 max_backups = 3; + + /* + Deprecated, use sweep_sat_per_vbyte. + The fee rate, in satoshis per vbyte, that will be used by the watchtower for + the justice transaction in the event of a channel breach. + */ + uint32 sweep_sat_per_byte = 4 [deprecated = true]; + + /* + The fee rate, in satoshis per vbyte, that will be used by the watchtower for + the justice transaction in the event of a channel breach. + */ + uint32 sweep_sat_per_vbyte = 5; +} + +message Tower { + // The identifying public key of the watchtower. + bytes pubkey = 1; + + // The list of addresses the watchtower is reachable over. + repeated string addresses = 2; + + // Deprecated, use the active_session_candidate field under the + // correct identifier in the client_type map. + // Whether the watchtower is currently a candidate for new sessions. + bool active_session_candidate = 3 [deprecated = true]; + + // Deprecated, use the num_sessions field under the correct identifier + // in the client_type map. + // The number of sessions that have been negotiated with the watchtower. + uint32 num_sessions = 4 [deprecated = true]; + + // Deprecated, use the sessions field under the correct identifier in the + // client_type map. + // The list of sessions that have been negotiated with the watchtower. + repeated TowerSession sessions = 5 [deprecated = true]; + + // A list sessions held with the tower. + repeated TowerSessionInfo session_info = 6; +} + +message TowerSessionInfo { + // Whether the watchtower is currently a candidate for new sessions. + bool active_session_candidate = 1; + + // The number of sessions that have been negotiated with the watchtower. + uint32 num_sessions = 2; + + // The list of sessions that have been negotiated with the watchtower. + repeated TowerSession sessions = 3; + + // The session's policy type. + PolicyType policy_type = 4; +} + +message ListTowersRequest { + // Whether we should include sessions with the watchtower in the response. + bool include_sessions = 1; + + // Whether to exclude exhausted sessions in the response info. This option + // is only meaningful if include_sessions is true. + bool exclude_exhausted_sessions = 2; +} + +message ListTowersResponse { + // The list of watchtowers available for new backups. + repeated Tower towers = 1; +} + +message StatsRequest { +} + +message StatsResponse { + /* + The total number of backups made to all active and exhausted watchtower + sessions. + */ + uint32 num_backups = 1; + + /* + The total number of backups that are pending to be acknowledged by all + active and exhausted watchtower sessions. + */ + uint32 num_pending_backups = 2; + + /* + The total number of backups that all active and exhausted watchtower + sessions have failed to acknowledge. + */ + uint32 num_failed_backups = 3; + + // The total number of new sessions made to watchtowers. + uint32 num_sessions_acquired = 4; + + // The total number of watchtower sessions that have been exhausted. + uint32 num_sessions_exhausted = 5; +} + +enum PolicyType { + // Selects the policy from the legacy tower client. + LEGACY = 0; + + // Selects the policy from the anchor tower client. + ANCHOR = 1; +} + +message PolicyRequest { + /* + The client type from which to retrieve the active offering policy. + */ + PolicyType policy_type = 1; +} + +message PolicyResponse { + /* + The maximum number of updates each session we negotiate with watchtowers + should allow. + */ + uint32 max_updates = 1; + + /* + Deprecated, use sweep_sat_per_vbyte. + The fee rate, in satoshis per vbyte, that will be used by watchtowers for + justice transactions in response to channel breaches. + */ + uint32 sweep_sat_per_byte = 2 [deprecated = true]; + + /* + The fee rate, in satoshis per vbyte, that will be used by watchtowers for + justice transactions in response to channel breaches. + */ + uint32 sweep_sat_per_vbyte = 3; +} diff --git a/status/manager.go b/status/manager.go index cb2f2befc..4035dc3ab 100644 --- a/status/manager.go +++ b/status/manager.go @@ -55,9 +55,13 @@ type subServer struct { // newSubServer constructs a new subServer. func newSubServer(disabled bool, opts ...SubServerOption) *subServer { - return &subServer{ + s := &subServer{ disabled: disabled, } + for _, opt := range opts { + opt(s) + } + return s } // Manager manages the status of any sub-server registered to it. It is also an diff --git a/terminal.go b/terminal.go index 3d0bc964d..d3960a833 100644 --- a/terminal.go +++ b/terminal.go @@ -196,15 +196,24 @@ type LightningTerminal struct { restHandler http.Handler restCancel func() + + mobileListener *bufconn.Listener + mobileReadyChan chan struct{} } // New creates a new instance of the lightning-terminal daemon. -func New() *LightningTerminal { +func New(listener *bufconn.Listener, readyChan chan struct{}) *LightningTerminal { return &LightningTerminal{ - statusMgr: status.NewStatusManager(), + statusMgr: status.NewStatusManager(), + mobileListener: listener, + mobileReadyChan: readyChan, } } +func (g *LightningTerminal) GetConfig() *Config { + return g.cfg +} + // Run starts everything and then blocks until either the application is shut // down or a critical error happens. func (g *LightningTerminal) Run() error { @@ -244,7 +253,7 @@ func (g *LightningTerminal) Run() error { // URI as soon as LND can accept the call, i.e. when the lnd sub-server // is in the "Wallet Ready" state. lndOverride := func(uri, manualStatus string) (bool, bool) { - if uri != "/lnrpc.State/GetState" { + if uri != "/lnrpc.State/GetState" && !strings.HasPrefix(uri, "/lnrpc.WalletUnlocker") { return false, false } @@ -283,19 +292,34 @@ func (g *LightningTerminal) Run() error { litrpc.RegisterProxyServer(g.rpcProxy.grpcServer, g.rpcProxy) litrpc.RegisterStatusServer(g.rpcProxy.grpcServer, g.statusMgr) - // Start the main web server that dispatches requests either to the - // static UI file server or the RPC proxy. This makes it possible to - // unlock lnd through the UI. - if err := g.startMainWebServer(); err != nil { - return fmt.Errorf("error starting main proxy HTTP server: %v", - err) - } + // Set up the in-memory listener + if g.mobileListener != nil && g.mobileReadyChan != nil { + log.Info("Setting up mobile listener") + tlsConfig, err := buildTLSConfigForHttp2(g.cfg) + if err != nil { + log.Infof("Failed to create mobileListener tlsConfig: %v", err) + os.Exit(1) + } + go func() { + tlsListener := tls.NewListener(g.mobileListener, tlsConfig) + close(g.mobileReadyChan) + _ = g.rpcProxy.grpcServer.Serve(tlsListener) + }() + } else { + // Start the main web server that dispatches requests either to the + // static UI file server or the RPC proxy. This makes it possible to + // unlock lnd through the UI. + if err := g.startMainWebServer(); err != nil { + return fmt.Errorf("error starting main proxy HTTP server: %v", + err) + } - // We'll also create a REST proxy that'll convert any REST calls to gRPC - // calls and forward them to the internal listener. - if g.cfg.EnableREST { - if err := g.createRESTProxy(); err != nil { - return fmt.Errorf("error creating REST proxy: %v", err) + // We'll also create a REST proxy that'll convert any REST calls to gRPC + // calls and forward them to the internal listener. + if g.cfg.EnableREST { + if err := g.createRESTProxy(); err != nil { + return fmt.Errorf("error creating REST proxy: %v", err) + } } }