This PR was created in order to help to debug the failures in:
https://github.com/lightningnetwork/lnd/issues/5113
We add some more contextual errors so we can figure out where the
assumptions of the current scan to delete function in the invoice
registry is incorrect.
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.
We extract common macaroon validating code into a method, and add a
method whitelist, for methods that won't need macaroons.
This give us explicit control over which methods don't require
macaroons, to avoid inadvertently adding RPCs that are unauthenticated.
For now this whitelist contains the WalletUnlocker methods, as the
wallet password is required to open the macaroon db.
This adds a new package rpcperms which houses the InterceptorChain
struct. This is a central place where we'll craft interceptors to use
for the GRPC server, which includes macaroon enforcement.
This let us add the interceptor chain to the GRPC server before the
macaroon service is ready, allowing us to avoid tearing down the GRPC
server after the wallet has been unlocked.
In order to be able to register the subservers with the root grpc server
before we have all dependencies available, we wrap them in an
GrpcHandler struct. This struct will initially hold an empty reference
to the subservers, which allows us to register with the GRPC server, and
later populate and create the subserver instance.