With this commit we allow a replacement message to be sent by the
middleware for a request type as well as the response type. This allows
an incoming RPC request to be modified before it is forwarded to lnd.
Because of the way the gRPC Receive() method is designed, we need a way
to replace a proto message with the content of another one without
replacing the original instance itself (e.g. overwrite all values in the
existing struct instance).
This commit adds a unique request ID that is the same for each gRPC
request and response intercept message or each request/response message
of a gRPC stream.
This commit adds a new unique intercept message ID that is different for
each message sent to an RPC middleware. This will allow us to re-purpose
the existing request ID field into its original intention, which was to
have a unique ID for a full gRPC request/response pair or gRPC stream as
a whole.
With this commit we introduce the concept of RPC middleware: A mechanism
similar to the existing channel or HTLC interceptors but this time for
gRPC messages themselves.
An RPC middleware can register itself to the main RPC server to get
notified each time a new gRPC request comes in, a gRPC response is sent
back or a streaming RPC is connected. The middleware can
validate/inspect incoming requests and modify/overwrite outgoing
responses.
Since this also opens the door for malicious software to interfere with
lnd in a negative way, we bind everything to macaroons with custom
caveat conditions: A middleware declares upon registration which custom
caveat name it can handle. Only client requests that send a macaroon
with that custom caveat will then be given to the middleware for
inspection. The only exception is if the middleware instead registers
to use the read-only mode. In that mode it will be able to intercept
all requests/responses, even those not made with a special encumbered
macaroon. But the middleware won't be able to alter responses in the
read-only mode. Therefore requests with the default, unencumbered macaroons
can never be modified by any middleware.