Skip to main content

RegisterRPCMiddleware

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!

Source: lightning.proto

gRPC

info

This is a bidirectional-streaming RPC

rpc RegisterRPCMiddleware (stream RPCMiddlewareResponse) returns (stream RPCMiddlewareRequest);

REST

HTTP MethodPath
POST /v1/middleware

Code Samples

const fs = require('fs');
const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');

const GRPC_HOST = 'localhost:10009'
const MACAROON_PATH = 'LND_DIR/data/chain/bitcoin/regtest/admin.macaroon'
const TLS_PATH = 'LND_DIR/tls.cert'

const loaderOptions = {
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true,
};
const packageDefinition = protoLoader.loadSync('lightning.proto', loaderOptions);
const lnrpc = grpc.loadPackageDefinition(packageDefinition).lnrpc;
process.env.GRPC_SSL_CIPHER_SUITES = 'HIGH+ECDSA';
const tlsCert = fs.readFileSync(TLS_PATH);
const sslCreds = grpc.credentials.createSsl(tlsCert);
const macaroon = fs.readFileSync(MACAROON_PATH).toString('hex');
const macaroonCreds = grpc.credentials.createFromMetadataGenerator(function(args, callback) {
let metadata = new grpc.Metadata();
metadata.add('macaroon', macaroon);
callback(null, metadata);
});
let creds = grpc.credentials.combineChannelCredentials(sslCreds, macaroonCreds);
let client = new lnrpc.Lightning(GRPC_HOST, creds);
let request = {
ref_msg_id: <uint64>,
register: <MiddlewareRegistration>,
feedback: <InterceptFeedback>,
};
let call = client.registerRPCMiddleware({});
call.on('data', function(response) {
// A response was received from the server.
console.log(response);
});
call.on('status', function(status) {
// The current status of the stream.
});
call.on('end', function() {
// The server has closed the stream.
});
call.write(request);
// Console output:
// {
// "request_id": <uint64>,
// "raw_macaroon": <bytes>,
// "custom_caveat_condition": <string>,
// "stream_auth": <StreamAuth>,
// "request": <RPCMessage>,
// "response": <RPCMessage>,
// "reg_complete": <bool>,
// "msg_id": <uint64>,
// }

Messages

lnrpc.RPCMiddlewareResponse

Source: lightning.proto

FieldgRPC TypeREST TypeREST Placement
ref_msg_id
uint64unknownunknown
register
MiddlewareRegistrationobjectunknown
feedback
InterceptFeedbackobjectunknown

lnrpc.RPCMiddlewareRequest

Source: lightning.proto

FieldgRPC TypeREST Type
request_id
uint64string
raw_macaroon
bytesstring
custom_caveat_condition
stringstring
stream_auth
StreamAuthobject
request
RPCMessageobject
response
RPCMessageobject
reg_complete
boolboolean
msg_id
uint64string

Nested Messages

lnrpc.MiddlewareRegistration

FieldgRPC TypeREST Type
middleware_name
stringstring
custom_macaroon_caveat_name
stringstring
read_only_mode
boolboolean

lnrpc.InterceptFeedback

FieldgRPC TypeREST Type
error
stringstring
replace_response
boolboolean
replacement_serialized
bytesstring

lnrpc.StreamAuth

FieldgRPC TypeREST Type
method_full_uri
stringstring

lnrpc.RPCMessage

FieldgRPC TypeREST Type
method_full_uri
stringstring
stream_rpc
boolboolean
type_name
stringstring
serialized
bytesstring
is_error
boolboolean