This adds support for notifying systemd about the state of LND. It
notifies systemd just before waiting for wallet password or, if
`wallet-password-file` was specified, right after unlocking the wallet.
This means that "ready" represents RPC being available for intended use.
It's intentional, so that client services can use `After=` in `systemd`
configuration to avoid misleading error messages about missing files or
refused connections.
Part of #4470
To have all the database backend related code in one place, we finally
also move the initialization of the wallet DB loader option into the
GetBackends() method.
The final database that needs to be made remote compatible is the
watchtower server and client database.
They are handled a bit differently because both of them are not always
active, only when specifically turned on in the config.
Even though the sphinx router's persistent replay log is not crucial in
the operation of lnd as its state can be re-created by creating a new
brontide connection, we want to make lnd fully stateless and therefore
have the option of not storing any state on disk.
The macaroon root keys should also be stored to the remote database if a
replicated backend such as etcd is used.
This commit refactors the macaroons service and wallet unlocker to
accept a kvdb backend directly instead of creating the bolt instance
automatically.
This commit gets rid of the concept of a local and remote database when
etcd is used. Instead the same backend is now used for both the
(previously renamed from local and remote DB) graph and channel state
databases.
This will make path finding extremely slow on etcd and will require
further optimizations and possibly a write-through cache for the graph
DB. But this is a requirement for making lnd itself fully stateless.
In order to separate our databases more clearly, we refactor the height
hint cache DB to use a kvdb backend instead of the channel DB instance
directly.
As a preparation to not have a local and remote version of the database
around anymore, we rename the variables into what their actual function
is. In case of the RPC server we even directly use the channel graph
instead of the DB instance. This should allow us to extract the channel
graph into its own, separate database (perhaps with better access
characteristics) in the future.
As a preparation to initialize more than just the channel database on
startup we introduce a new struct that holds a reference to each of our
database instances.
This changes file reation mode on admin macaroon from 0600 to 0640. The
reason is to make permission management easier.
Closes#4385
**Is this safe?**
Yes, it is. Assuming a reasonably secure Linux system, it will have a
separate group for each user. E.g. a new user `lnd` gets assigned group
`lnd` which nothing else belongs to. A system that does not do this is
inherently broken already.
Since there is no other user in the group, no other user can read admin
macaroon unless the administrator explicitly allowed it. Thus there's no
harm allowing group read.
As requested by users of node bundle software. They want to use the
wallet-unlock-password-file configuration option in their
default/template config file. This makes the first-time lnd setup a bit
more tricky since lnd will fail with an error if no wallet exists yet
while that config option is used.
The new wallet-unlock-allow-create option instructs lnd to not fail if
no wallet exists yet but instead spin up its unlocker RPC as it would
without the wallet-unlock-password-file being present.
This is not recommended for auto-provisioned or high-security systems
because the wallet creation RPC is unauthenticated and an attacker could
inject a seed while lnd is in that state.
In automated or unattended setups such as cluster/container
environments, unlocking the wallet through RPC presents a set of
challenges. Usually the password is present as a file somewhere in the
container already anyway so we might also just read it from there.
This commit adds a new "waiting to start" state which may be used to
query if we're still waiting to become the cluster leader. Once leader
we advance the state to "wallet not exist" or "wallet locked" given
wallet availablity.
This commit also changes the order of DB init to be run after the RPC
server is up. This will allow us to later add an RPC endpoint to be used
to query leadership status.
The grpc-gateway library that is used to transform REST calls into gRPC
uses a different method for reading a request body stream depending on
whether the RPC is a request-streaming one or not. We can't really find
out what kind of RPC the user is calling at runtime, so we add a new
parameter to the proxy that lists all request-streaming RPC calls.
In any case the client _has_ to send one request message initially to
kick off the request processing. Normally this can just be an empty
message. This can lead to problems if that empty message is not
expected by the gRPC server. But for the currently existing two
client-streaming RPCs this will only trigger a warning
(HTLC interceptor) or be ignored (channel acceptor).
In this commit the location of where chain control services
are stopped is shifted to be closer to the point they are started.
Stopping of two services: "wallet" and "feeEstimator" that are started
inside the "newChainControlFromConfig" was shifted from server.go to
the cleanup function.
In addition the chainView.Stop was also removed from the server.Stop as
it is already handled by the router, where it is being started.
The --profile flag now accepts both a port and a host:port string.
If profile is set to a port, then pprof debugging information will
be served over localhost. Otherwise, we will attempt to serve pprof
information on the specified host:port (if we are allowed to listen
on it.)
We default to the safe option as if the port is connectable, anybody
can connect and see debugging information.
See: https://mmcloughlin.com/posts/your-pprof-is-showing
Downloading every block that contains a channel point takes a very long
time when syncing the graph on mainnet with Neutrino. Therefore it makes
sense to use routing.assumechanvalid=true since by using Neutrino a user
already accepts the different trust model.
Apparently the existence or meaning of the routing.assumechanvalid flag
is unknown to a lot of users and is overlooked.
This commit basically sets the default to routing.assumechanvalid=true
for Neutrino. Because the CLI library doesn't support setting a bool
value to false by the user if the default is true, we need to add an
additional flag that is the inverse of the routing one, just for the
case where a Neutrino user explicitly wants to turn on channel
validation.
After unification of the WalletUnlocker and RPC services on the same gRPC
server, the WalletUnlocker will no longer be shut down after the wallet
has been unlocked.
In case --no-macaroons was used, this lead to the caller getting stuck
after unlocking the wallet, since we would wait for a response on the
MacResponseChan. Earlier we would close the MacResponseChan always
when shutting down the WalletUnlocker, but this is no longer done.
To fix this we close this channel after the wallet is unlocked,
regardless of which combination of --no-macaroons and --noseedbackup
that is being used.
This commit makes us gate the calls to the RPC servers according to the
current RPC state. This ensures we won't try to call the RPC server
before it has been fully initialized, and that we won't call the
walletUnlocker after the wallet already has been unlocked.
This commit achieves what we have been building up to: running the
WalletUnlockerService and the LightningService on the same gRPC server
simultaneously!
To achieve this, we first create the RPC server in a "interface only"
way, only creating the struct and setting the dependencies we have
available before the wallet has been unlocked. After the wallet has been
unlocked and we have created all the subsystems we need, we add those to
the RPC server, and start the sub-servers.
This means that the WalletUnlockerService and the LightningService both
will be registered and available at all times on the gRPC server.
However, before the wallet has been unlocked, the LightningService
should not be used since the RPC server is not yet ready to handle the
calls. Similarly, after the wallet has been unlocked, the
WalletUnlockerService should not be used. This we will ensure in
following commits.
We don't have to define the external subserver config more than once, so
it is not needed to be defined for every listener. Instead we move it to
the ListenerConfig.