From 61f7640ec43d8eb4bdf45ae0ae813832ea3bd176 Mon Sep 17 00:00:00 2001 From: "nicolas.dorier" Date: Wed, 7 Mar 2018 13:50:44 -0500 Subject: [PATCH] Adapt Dockerfile for BTCPay deployment --- .github/workflows/docker.yml | 34 ++++++++ Dockerfile | 41 ++++++++- plugins/Cargo.toml | 1 - plugins/Makefile | 14 +--- plugins/bcli.c | 22 +++-- plugins/grpc-plugin/Cargo.toml | 30 ------- plugins/grpc-plugin/README.md | 144 -------------------------------- plugins/grpc-plugin/src/main.rs | 99 ---------------------- plugins/grpc-plugin/src/tls.rs | 120 -------------------------- tools/docker-entrypoint.sh | 69 ++++++++++++++- 10 files changed, 150 insertions(+), 424 deletions(-) create mode 100644 .github/workflows/docker.yml delete mode 100644 plugins/grpc-plugin/Cargo.toml delete mode 100644 plugins/grpc-plugin/README.md delete mode 100644 plugins/grpc-plugin/src/main.rs delete mode 100644 plugins/grpc-plugin/src/tls.rs diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 000000000000..f04f271478c6 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,34 @@ +name: Docker packaging +on: + push: + tags: + - 'basedon-*' + +jobs: + main: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - + name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - + name: Environment variables + run: env + - + name: Create images + env: + DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }} + DOCKERHUB_PASS: ${{ secrets.DOCKERHUB_PASS }} + DOCKERHUB_REPO: ${{ vars.DOCKERHUB_REPO }} + shell: bash + run: | + LATEST_TAG=${GITHUB_REF#refs/tags/} + LATEST_TAG=${LATEST_TAG:8} #trim "basedon-" from tag + echo "$DOCKERHUB_PASS" | docker login -u "$DOCKERHUB_USER" --password-stdin + docker buildx create --use + DOCKER_BUILDX_OPTS="--platform linux/amd64,linux/arm64,linux/arm/v7 --push" + docker buildx build $DOCKER_BUILDX_OPTS -t $DOCKERHUB_REPO:$LATEST_TAG . \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index a5ef573f0630..19dfc3b40327 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,7 +5,30 @@ # * final: Copy the binaries required at runtime # The resulting image uploaded to dockerhub will only contain what is needed for runtime. # From the root of the repository, run "docker build -t yourimage:yourtag ." -FROM debian:bullseye-slim as downloader + +FROM debian:bullseye-slim as base-downloader + +FROM --platform=$BUILDPLATFORM debian:bullseye-slim as base-downloader +RUN set -ex \ + && apt-get update \ + && apt-get install -qq --no-install-recommends ca-certificates dirmngr wget + +FROM --platform=$BUILDPLATFORM base-downloader as base-downloader-linux-amd64 +ENV TARBALL_ARCH_FINAL=x86_64-linux-gnu +ENV DESCHASHPLUGIN_ARCH=linux-amd64 +ENV DESCHASHPLUGIN_HASH=deadc00c68fac80b2718d92f69bf06acd8fff646228d497bbb76a4f0a12ca217 + +FROM --platform=$BUILDPLATFORM base-downloader as base-downloader-linux-arm64 +ENV TARBALL_ARCH_FINAL=aarch64-linux-gnu +ENV DESCHASHPLUGIN_ARCH=linux-arm64 +ENV DESCHASHPLUGIN_HASH=d48c3e5aede77bd9cb72d78689ce12c0327f624435cb0496b3eacb92df416363 + +FROM --platform=$BUILDPLATFORM base-downloader as base-downloader-linux-arm +ENV TARBALL_ARCH_FINAL=arm-linux-gnueabihf +ENV DESCHASHPLUGIN_ARCH=linux-arm +ENV DESCHASHPLUGIN_HASH=f7df336c72dd1674bd18ff23862a410b6a9691a3e13752264dcffa0950e21c74 + +FROM base-downloader-${TARGETOS}-${TARGETARCH} as downloader RUN set -ex \ && apt-get update \ @@ -14,9 +37,7 @@ RUN set -ex \ WORKDIR /opt -ARG BITCOIN_VERSION=22.0 -ARG TARBALL_ARCH=x86_64-linux-gnu -ENV TARBALL_ARCH_FINAL=$TARBALL_ARCH +ENV BITCOIN_VERSION=22.0 ENV BITCOIN_TARBALL bitcoin-${BITCOIN_VERSION}-${TARBALL_ARCH_FINAL}.tar.gz ENV BITCOIN_URL https://bitcoincore.org/bin/bitcoin-core-$BITCOIN_VERSION/$BITCOIN_TARBALL ENV BITCOIN_ASC_URL https://bitcoincore.org/bin/bitcoin-core-$BITCOIN_VERSION/SHA256SUMS @@ -39,6 +60,14 @@ RUN mkdir /opt/litecoin && cd /opt/litecoin \ && tar -xzvf litecoin.tar.gz litecoin-$LITECOIN_VERSION/bin/litecoin-cli --strip-components=1 --exclude=*-qt \ && rm litecoin.tar.gz +ENV DESCHASHPLUGIN_URL https://github.com/nbd-wtf/invoicewithdescriptionhash/releases/download/v1.4/invoicewithdescriptionhash-v1.4-${DESCHASHPLUGIN_ARCH}.tar.gz +ENV DESCHASHPLUGIN_SHA256 ${DESCHASHPLUGIN_HASH} +RUN mkdir /opt/deschashplugin && cd /opt/deschashplugin \ + && wget -qO invoicewithdescriptionhash.tar.gz "$DESCHASHPLUGIN_URL" \ + && echo "$DESCHASHPLUGIN_SHA256 invoicewithdescriptionhash.tar.gz" | sha256sum -c - \ + && tar -xzvf invoicewithdescriptionhash.tar.gz && rm invoicewithdescriptionhash.tar.gz \ + && chmod a+x invoicewithdescriptionhash + FROM debian:bullseye-slim as builder ENV LIGHTNINGD_VERSION=master @@ -135,6 +164,8 @@ ENV LIGHTNINGD_PORT=9735 ENV LIGHTNINGD_NETWORK=bitcoin RUN mkdir $LIGHTNINGD_DATA && \ + mkdir /etc/bundledplugins && \ + mkdir $LIGHTNINGD_DATA/plugins && \ touch $LIGHTNINGD_DATA/config VOLUME [ "/root/.lightning" ] @@ -142,6 +173,8 @@ COPY --from=builder /tmp/lightning_install/ /usr/local/ COPY --from=builder /usr/local/lib/python3.9/dist-packages/ /usr/local/lib/python3.9/dist-packages/ COPY --from=downloader /opt/bitcoin/bin /usr/bin COPY --from=downloader /opt/litecoin/bin /usr/bin +COPY --from=downloader /opt/deschashplugin $LIGHTNINGD_DATA/plugins +COPY --from=downloader /opt/deschashplugin /etc/bundledplugins COPY tools/docker-entrypoint.sh entrypoint.sh EXPOSE 9735 9835 diff --git a/plugins/Cargo.toml b/plugins/Cargo.toml index 407524e54d87..efb0025df3a0 100644 --- a/plugins/Cargo.toml +++ b/plugins/Cargo.toml @@ -27,4 +27,3 @@ tracing = { version = "^0.1", features = ["async-await", "log"] } [dev-dependencies] tokio = { version = "1", features = ["macros", "rt-multi-thread", ] } -cln-grpc = { version = "0.1", path = "../cln-grpc" } diff --git a/plugins/Makefile b/plugins/Makefile index 0da2e5738dd0..7a2771229611 100644 --- a/plugins/Makefile +++ b/plugins/Makefile @@ -121,15 +121,6 @@ endif PLUGINS := $(C_PLUGINS) PLUGIN_ALL_OBJS := $(PLUGIN_ALL_SRC:.c=.o) -ifneq ($(RUST),0) -# Builtin plugins must be in this plugins dir to work when we're executed -# *without* make install. -plugins/cln-grpc: target/${RUST_PROFILE}/cln-grpc - @cp $< $@ - -PLUGINS += plugins/cln-grpc -endif - PLUGIN_COMMON_OBJS := \ bitcoin/base58.o \ bitcoin/block.o \ @@ -253,11 +244,8 @@ CLN_PLUGIN_EXAMPLES := \ CLN_PLUGIN_SRC = $(shell find plugins/src -name "*.rs") -target/${RUST_PROFILE}/cln-grpc: ${CLN_PLUGIN_SRC} - cargo build ${CARGO_OPTS} --bin cln-grpc - ifneq ($(RUST),0) -DEFAULT_TARGETS += $(CLN_PLUGIN_EXAMPLES) plugins/cln-grpc +DEFAULT_TARGETS += $(CLN_PLUGIN_EXAMPLES) endif clean: plugins-clean diff --git a/plugins/bcli.c b/plugins/bcli.c index e04159b44377..fee4aed57617 100644 --- a/plugins/bcli.c +++ b/plugins/bcli.c @@ -969,6 +969,7 @@ static void wait_and_check_bitcoind(struct plugin *p) pid_t child; const char **cmd = gather_args(bitcoind, "getnetworkinfo", NULL); bool printed = false; + bool isWarmup = false; char *output = NULL; for (;;) { @@ -1004,17 +1005,20 @@ static void wait_and_check_bitcoind(struct plugin *p) /* bitcoin/src/rpc/protocol.h: * RPC_IN_WARMUP = -28, //!< Client still warming up */ - if (WEXITSTATUS(status) != 28) { - if (WEXITSTATUS(status) == 1) - bitcoind_failure(p, "Could not connect to bitcoind using" - " bitcoin-cli. Is bitcoind running?"); - bitcoind_failure(p, tal_fmt(bitcoind, "%s exited with code %i: %s", - cmd[0], WEXITSTATUS(status), output)); - } + isWarmup = WEXITSTATUS(status) == 28; if (!printed) { - plugin_log(p, LOG_UNUSUAL, - "Waiting for bitcoind to warm up..."); + if (isWarmup) + { + plugin_log(p, LOG_UNUSUAL, + "Waiting for bitcoind to warm up..."); + } + else + { + plugin_log(p, LOG_UNUSUAL, + tal_fmt(bitcoind, "%s exited with code %i: %s... retrying", + cmd[0], WEXITSTATUS(status), output)); + } printed = true; } sleep(1); diff --git a/plugins/grpc-plugin/Cargo.toml b/plugins/grpc-plugin/Cargo.toml deleted file mode 100644 index dcf404fafc35..000000000000 --- a/plugins/grpc-plugin/Cargo.toml +++ /dev/null @@ -1,30 +0,0 @@ -[package] -edition = "2021" -name = "cln-grpc-plugin" -version = "0.1.5" - -description = "A Core Lightning plugin that re-exposes the JSON-RPC over grpc. Authentication is done via mTLS." -license = "MIT" -repository = "https://github.com/ElementsProject/lightning" -documentation = "https://docs.rs/crate/cln-grpc-plugin/" - -[[bin]] -name = "cln-grpc" -path = "src/main.rs" - -[dependencies] -anyhow = "1.0" -log = "0.4" -prost = "0.11" -rcgen = { version = "0.10", features = ["pem", "x509-parser"] } -cln-grpc = { version = "0.1", features = ["server"], path = "../../cln-grpc"} -cln-plugin = { version = "0.1", path = "../../plugins" } -cln-rpc = { version = "0.1", path = "../../cln-rpc" } - -[dependencies.tokio] -features = ["net", "rt-multi-thread"] -version = "1" - -[dependencies.tonic] -features = ["tls", "transport"] -version = "0.8" diff --git a/plugins/grpc-plugin/README.md b/plugins/grpc-plugin/README.md deleted file mode 100644 index 0894c49e17b4..000000000000 --- a/plugins/grpc-plugin/README.md +++ /dev/null @@ -1,144 +0,0 @@ -# GRPC plugin for Core Lightning - -This plugin exposes the JSON-RPC interface through grpc over the -network. It listens on a configurable port, authenticates clients -using mTLS certificates, and will forward any request to the JSON-RPC -interface, performing translations from protobuf to JSON and back. - - -## Getting started - -The plugin only runs when `lightningd` is configured with the option -`--grpc-port`. Upon starting the plugin generates a number of files, -if they don't already exist: - - - `ca.pem` and `ca-key.pem`: These are the certificate and private - key for your own certificate authority. The plugin will only accept - incoming connections using certificates that are signed by theis - CA. - - `server.pem` and `server-key.pem`: this is the identity - (certificate and private key) used by the plugin to authenticate - itself. It is signed by the CA, and the client will verify its - identity. - - `client.pem` and `client-key.pem`: this is an example identity that - can be used by a client to connect to the plugin, and issue - requests. It is also signed by the CA. - -These files are generated with sane defaults, however you can generate -custom certificates should you require some changes (see below for -details). - -## Connecting - -The client needs a valid mTLS identity in order to connect to the -plugin, so copy over the `ca.pem`, `client.pem` and `client-key.pem` -files from the node. The RPC interface is described in the [protobuf -file][proto], and we'll first need to generate language specific -bindings. - -In this example we walk through the steps for python, however they are -mostly the same for other languages. - -We start by downloading the dependencies and `protoc` compiler: - -```bash -pip install grpcio-tools -``` - -Next we generate the bindings in the current directory: - -```bash -python -m grpc_tools.protoc \ - -I path/to/cln-grpc/proto \ - path/to/cln-grpc/proto/node.proto \ - --python_out=. \ - --grpc_python_out=. \ - --experimental_allow_proto3_optional -``` - -This will generate two files in the current directory: - - - `node_pb2.py`: the description of the protobuf messages we'll be - exchanging with the server. - - `node_pb2_grpc.py`: the service and method stubs representing the - server-side methods as local objects and associated methods. - -And finally we can use the generated stubs and mTLS identity to -connect to the node: - -```python -from pathlib import Path -from node_pb2_grpc import NodeStub -import node_pb2 - -p = Path(".") -cert_path = p / "client.pem" -key_path = p / "client-key.pem" -ca_cert_path = p / "ca.pem" - -creds = grpc.ssl_channel_credentials( - root_certificates=ca_cert_path.open('rb').read(), - private_key=key_path.open('rb').read(), - certificate_chain=cert_path.open('rb').read() -) - -channel = grpc.secure_channel( - f"localhost:{grpc_port}", - creds, - options=(('grpc.ssl_target_name_override', 'cln'),) -) -stub = NodeStub(channel) - -print(stub.Getinfo(node_pb2.GetinfoRequest())) -``` - -In this example we first local the client identity, as well as the CA -certificate so we can verify the server's identity against it. We then -create a `creds` instance using those details. Next we open a secure -channel, i.e., a channel over TLS with verification of identities. - -Notice that we override the expected SSL name with `cln`. This is -required because the plugin does not know the domain under which it -will be reachable, and will therefore use `cln` as a standin. See -custom certificate generation for how this could be changed. - -We then use the channel to instantiate the `NodeStub` representing the -service and its methods, so we can finally call the `Getinfo` method -with default arguments. - -## Generating custom certificates - -The automatically generated mTLS certificate will not know about -potential domains that it'll be served under, and will chose a number -of other parameters by default. If you'd like to generate a server -certificate with a custom domain you can use the following: - - -```bash -openssl genrsa -out server-key.pem 2048 -``` - -This generates the private key. Next we create a Certificate Signature Request (CSR) that we can then process using our CA identity: - -```bash -openssl req -key server-key.pem -new -out server.csr -``` - -You will be asked a number of questions, the most important of which -is the _Common Name_, which you should set to the domain name you'll -be serving the interface under. Next we can generate the actual -certificate by processing the request with the CA identity: - -```bash -openssl x509 -req -CA ca.pem -CAkey ca-key.pem \ - -in server.csr \ - -out server.pem \ - -days 365 -CAcreateserial -``` - -This will finally create the `server.pem` file, signed by the CA, -allowing you to access the node through its real domain name. You can -now move `server.pem` and `server-key.pem` into the lightning -directory, and they should be picked up during the start. - -[proto]: https://github.com/ElementsProject/lightning/blob/master/cln-grpc/proto/node.proto diff --git a/plugins/grpc-plugin/src/main.rs b/plugins/grpc-plugin/src/main.rs deleted file mode 100644 index 303f0fc4307e..000000000000 --- a/plugins/grpc-plugin/src/main.rs +++ /dev/null @@ -1,99 +0,0 @@ -use anyhow::{Context, Result}; -use cln_grpc::pb::node_server::NodeServer; -use cln_plugin::{options, Builder}; -use log::{debug, warn}; -use std::net::SocketAddr; -use std::path::PathBuf; - -mod tls; - -#[derive(Clone, Debug)] -struct PluginState { - rpc_path: PathBuf, - identity: tls::Identity, - ca_cert: Vec, -} - -const OPTION_GRPC_PORT : options::IntegerConfigOption = options::ConfigOption::new_i64_no_default( - "grpc-port", - "Which port should the grpc plugin listen for incoming connections?"); - -#[tokio::main(flavor = "current_thread")] -async fn main() -> Result<()> { - debug!("Starting grpc plugin"); - - let directory = std::env::current_dir()?; - - let plugin = match Builder::new(tokio::io::stdin(), tokio::io::stdout()) - .option(OPTION_GRPC_PORT) - .configure() - .await? - { - Some(p) => p, - None => return Ok(()), - }; - - let bind_port = match plugin.option(&OPTION_GRPC_PORT).unwrap() { - Some(port) => port, - None => { - log::info!("'grpc-port' options i not configured. exiting."); - plugin - .disable("Missing 'grpc-port' option") - .await?; - return Ok(()) - } - }; - - let (identity, ca_cert) = tls::init(&directory)?; - - let state = PluginState { - rpc_path: PathBuf::from(plugin.configuration().rpc_file.as_str()), - identity, - ca_cert, - }; - - let plugin = plugin.start(state.clone()).await?; - - let bind_addr: SocketAddr = format!("0.0.0.0:{}", bind_port).parse().unwrap(); - - tokio::select! { - _ = plugin.join() => { - // This will likely never be shown, if we got here our - // parent process is exiting and not processing out log - // messages anymore. - debug!("Plugin loop terminated") - } - e = run_interface(bind_addr, state) => { - warn!("Error running grpc interface: {:?}", e) - } - } - Ok(()) -} - -async fn run_interface(bind_addr: SocketAddr, state: PluginState) -> Result<()> { - let identity = state.identity.to_tonic_identity(); - let ca_cert = tonic::transport::Certificate::from_pem(state.ca_cert); - - let tls = tonic::transport::ServerTlsConfig::new() - .identity(identity) - .client_ca_root(ca_cert); - - let server = tonic::transport::Server::builder() - .tls_config(tls) - .context("configuring tls")? - .add_service(NodeServer::new( - cln_grpc::Server::new(&state.rpc_path) - .await - .context("creating NodeServer instance")?, - )) - .serve(bind_addr); - - debug!( - "Connecting to {:?} and serving grpc on {:?}", - &state.rpc_path, &bind_addr - ); - - server.await.context("serving requests")?; - - Ok(()) -} diff --git a/plugins/grpc-plugin/src/tls.rs b/plugins/grpc-plugin/src/tls.rs deleted file mode 100644 index 8bd19848178e..000000000000 --- a/plugins/grpc-plugin/src/tls.rs +++ /dev/null @@ -1,120 +0,0 @@ -//! Utilities to manage TLS certificates. -use anyhow::{Context, Result}; -use log::debug; -use rcgen::{Certificate, KeyPair}; -use std::path::Path; - -/// Just a wrapper around a certificate and an associated keypair. -#[derive(Clone, Debug)] -pub(crate) struct Identity { - key: Vec, - certificate: Vec, -} - -impl Identity { - fn to_certificate(&self) -> Result { - let keystr = String::from_utf8_lossy(&self.key); - let key = KeyPair::from_pem(&keystr)?; - let certstr = String::from_utf8_lossy(&self.certificate); - let params = rcgen::CertificateParams::from_ca_cert_pem(&certstr, key)?; - let cert = Certificate::from_params(params)?; - Ok(cert) - } - - pub fn to_tonic_identity(&self) -> tonic::transport::Identity { - tonic::transport::Identity::from_pem(&self.certificate, &self.key) - } -} - -/// Ensure that we have a certificate authority, and child keypairs -/// and certificates for the server and the client. It'll generate -/// them in the provided `directory`. The following files are -/// included: -/// -/// - `ca.pem`: The self-signed certificate of the CA -/// - `ca-key.pem`: The key used by the CA to sign certificates -/// - `server.pem`: The server certificate, signed by the CA -/// - `server-key.pem`: The server private key -/// - `client.pem`: The client certificate, signed by the CA -/// - `client-key.pem`: The client private key -/// -/// The `grpc-plugin` will use the `server.pem` certificate, while a -/// client is supposed to use the `client.pem` and associated -/// keys. Notice that this isn't strictly necessary since the server -/// will accept any client that is signed by the CA. In future we -/// might add runes, making the distinction more important. -/// -/// Returns the server identity and the root CA certificate. -pub(crate) fn init(directory: &Path) -> Result<(Identity, Vec)> { - let ca = generate_or_load_identity("cln Root CA", directory, "ca", None)?; - let server = generate_or_load_identity("cln grpc Server", directory, "server", Some(&ca))?; - let _client = generate_or_load_identity("cln grpc Client", directory, "client", Some(&ca))?; - Ok((server, ca.certificate)) -} - -/// Generate a given identity -fn generate_or_load_identity( - name: &str, - directory: &Path, - filename: &str, - parent: Option<&Identity>, -) -> Result { - use std::io::Write; - use std::os::unix::fs::PermissionsExt; - // Just our naming convention here. - let cert_path = directory.join(format!("{}.pem", filename)); - let key_path = directory.join(format!("{}-key.pem", filename)); - // Did we have to generate a new key? In that case we also need to - // regenerate the certificate - if !key_path.exists() || !cert_path.exists() { - debug!( - "Generating a new keypair in {:?}, it didn't exist", - &key_path - ); - let keypair = KeyPair::generate(&rcgen::PKCS_ECDSA_P256_SHA256)?; - - // Create the file, but make it user-readable only: - let mut file = std::fs::File::create(&key_path)?; - let mut perms = std::fs::metadata(&key_path)?.permissions(); - perms.set_mode(0o600); - std::fs::set_permissions(&key_path, perms)?; - - // Only after changing the permissions we can write the - // private key - file.write_all(keypair.serialize_pem().as_bytes())?; - drop(file); - - debug!( - "Generating a new certificate for key {:?} at {:?}", - &key_path, &cert_path - ); - - // Configure the certificate we want. - let subject_alt_names = vec!["cln".to_string(), "localhost".to_string()]; - let mut params = rcgen::CertificateParams::new(subject_alt_names); - params.key_pair = Some(keypair); - params.alg = &rcgen::PKCS_ECDSA_P256_SHA256; - if parent.is_none() { - params.is_ca = rcgen::IsCa::Ca(rcgen::BasicConstraints::Unconstrained); - } else { - params.is_ca = rcgen::IsCa::NoCa; - } - params - .distinguished_name - .push(rcgen::DnType::CommonName, name); - - let cert = Certificate::from_params(params)?; - std::fs::write( - &cert_path, - match parent { - None => cert.serialize_pem()?, - Some(ca) => cert.serialize_pem_with_signer(&ca.to_certificate()?)?, - }, - ) - .context("writing certificate to file")?; - } - - let key = std::fs::read(&key_path)?; - let certificate = std::fs::read(cert_path)?; - Ok(Identity { certificate, key }) -} diff --git a/tools/docker-entrypoint.sh b/tools/docker-entrypoint.sh index 8d7bbfd2d920..d248d7dcf466 100755 --- a/tools/docker-entrypoint.sh +++ b/tools/docker-entrypoint.sh @@ -2,19 +2,80 @@ : "${EXPOSE_TCP:=false}" -networkdatadir="${LIGHTNINGD_DATA}/${LIGHTNINGD_NETWORK}" +cat <<-EOF > "$LIGHTNINGD_DATA/config" +${LIGHTNINGD_OPT} +bind-addr=0.0.0.0:${LIGHTNINGD_PORT} +EOF + +LIGHTNINGD_NETWORK_NAME="" + +if [ "$LIGHTNINGD_CHAIN" == "btc" ] && [ "$LIGHTNINGD_NETWORK" == "mainnet" ]; then + LIGHTNINGD_NETWORK_NAME="bitcoin" +elif [ "$LIGHTNINGD_CHAIN" == "btc" ] && [ "$LIGHTNINGD_NETWORK" == "testnet" ]; then + LIGHTNINGD_NETWORK_NAME="testnet" +elif [ "$LIGHTNINGD_CHAIN" == "btc" ] && [ "$LIGHTNINGD_NETWORK" == "regtest" ]; then + LIGHTNINGD_NETWORK_NAME="regtest" +elif [ "$LIGHTNINGD_CHAIN" == "ltc" ] && [ "$LIGHTNINGD_NETWORK" == "mainnet" ]; then + LIGHTNINGD_NETWORK_NAME="litecoin" +elif [ "$LIGHTNINGD_CHAIN" == "ltc" ] && [ "$LIGHTNINGD_NETWORK" == "testnet" ]; then + LIGHTNINGD_NETWORK_NAME="litecoin-testnet" +else + echo "Invalid combinaion of LIGHTNINGD_NETWORK and LIGHTNINGD_CHAIN. LIGHTNINGD_CHAIN should be btc or ltc. LIGHTNINGD_NETWORK should be mainnet, testnet or regtest." + echo "ltc regtest is not supported" + exit +fi + +echo "network=$LIGHTNINGD_NETWORK_NAME" >> "$LIGHTNINGD_DATA/config" +echo "network=$LIGHTNINGD_NETWORK_NAME added in $LIGHTNINGD_DATA/config" + +echo "disable-plugin=clnrest.py" >> "$LIGHTNINGD_DATA/config" +echo "disable-plugin=clnrest.py added in $LIGHTNINGD_DATA/config" + +if [[ "${LIGHTNINGD_ANNOUNCEADDR}" ]]; then + echo "announce-addr=$LIGHTNINGD_ANNOUNCEADDR:${LIGHTNINGD_PORT}" >> "$LIGHTNINGD_DATA/config" +fi + +if [[ "${LIGHTNINGD_ALIAS}" ]]; then + # This allow to strip this parameter if LND_ALIGHTNINGD_ALIASLIAS is empty or null, and truncate it + LIGHTNINGD_ALIAS="$(echo "$LIGHTNINGD_ALIAS" | cut -c -32)" + echo "alias=$LIGHTNINGD_ALIAS" >> "$LIGHTNINGD_DATA/config" + echo "alias=$LIGHTNINGD_ALIAS added to $LIGHTNINGD_DATA/config" +fi + +if [[ "${LIGHTNINGD_READY_FILE}" ]]; then + echo "Waiting $LIGHTNINGD_READY_FILE to be created..." + while [ ! -f "$LIGHTNINGD_READY_FILE" ]; do sleep 1; done + echo "The chain is fully synched" +fi + +if [[ "${LIGHTNINGD_HIDDENSERVICE_HOSTNAME_FILE}" ]]; then + echo "Waiting $LIGHTNINGD_HIDDENSERVICE_HOSTNAME_FILE to be created by tor..." + while [ ! -f "$LIGHTNINGD_HIDDENSERVICE_HOSTNAME_FILE" ]; do sleep 1; done + HIDDENSERVICE_ONION="$(head -n 1 "$LIGHTNINGD_HIDDENSERVICE_HOSTNAME_FILE"):${LIGHTNINGD_PORT}" + echo "announce-addr=$HIDDENSERVICE_ONION" >> "$LIGHTNINGD_DATA/config" + echo "announce-addr=$HIDDENSERVICE_ONION added to $LIGHTNINGD_DATA/config" +fi + +if ! grep -q "^rpc-file=" "$LIGHTNINGD_DATA/config"; then + echo "rpc-file=$LIGHTNINGD_DATA/lightning-rpc" >> "$LIGHTNINGD_DATA/config" + echo "rpc-file=$LIGHTNINGD_DATA/lightning-rpc added to $LIGHTNINGD_DATA/config" +fi + +echo "Installing bundled plugins" +mkdir -p "$LIGHTNINGD_DATA/plugins" +cp -u /etc/bundledplugins/* $LIGHTNINGD_DATA/plugins/ set -m -lightningd --network="${LIGHTNINGD_NETWORK}" "$@" & +lightningd "$@" & echo "Core-Lightning starting" while read -r i; do if [ "$i" = "lightning-rpc" ]; then break; fi; done \ - < <(inotifywait -e create,open --format '%f' --quiet "${networkdatadir}" --monitor) + < <(inotifywait -e create,open --format '%f' --quiet "$LIGHTNINGD_DATA" --monitor) if [ "$EXPOSE_TCP" == "true" ]; then echo "Core-Lightning started, RPC available on port $LIGHTNINGD_RPC_PORT" - socat "TCP4-listen:$LIGHTNINGD_RPC_PORT,fork,reuseaddr" "UNIX-CONNECT:${networkdatadir}/lightning-rpc" & + socat "TCP4-listen:$LIGHTNINGD_RPC_PORT,fork,reuseaddr" "UNIX-CONNECT:$LIGHTNINGD_DATA/lightning-rpc" & fi # Now run any scripts which exist in the lightning-poststart.d directory