Skip to content

Commit

Permalink
Merge pull request #158 from Ride-The-Lightning/Release-v0.10.0
Browse files Browse the repository at this point in the history
Release v0.10.0
  • Loading branch information
saubyk authored Feb 9, 2023
2 parents 3f8e608 + 24ed841 commit 2e01028
Show file tree
Hide file tree
Showing 14 changed files with 186 additions and 81 deletions.
15 changes: 10 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,12 @@ For running the server, rename the file `sample-cl-rest-config.json` to `cl-rest
- LNRPCPATH (Default: ` `)
- RPCCOMMANDS (Default: `["*"]`)
- DOMAIN (Default: `localhost`)
- BIND (Default: `::`)

#### Option 2: With the plugin configuration, if used as a plugin

NOTE: Node.js plugins might not work with lightningd.service setting `MemoryDenyWriteExecute=true` as it denies the creation of writable and executable memory mappings. Ref: https://github.com/Ride-The-Lightning/c-lightning-REST/issues/116

If running as a plugin, configure the below options in your c-lightning `config` file:
- `rest-port`
- `rest-docport`
Expand All @@ -56,6 +60,7 @@ If running as a plugin, configure the below options in your c-lightning `config`
- `rest-lnrpcpath`
- `rest-rpc`
- `rest-domain`
- `rest-bind`

Defaults are the same as in option # 1 with the exception that `rest-rpc` is a comma separated string.

Expand All @@ -72,15 +77,15 @@ Pass arguments when launching lightningd:

`$ lightningd --plugin=PATH_TO_PLUGIN [--rest-port=N] [--rest-protocol=http|https] [--rest-execmode=MODE]`

E.g. `$ lightningd --plugin=/Users/<user>/c-lightning-REST/plugin.js --rest-port=3003`
E.g. `$ lightningd --plugin=/Users/<user>/c-lightning-REST/clrest.js --rest-port=3003`

OR

Set `plugin`, `[rest-port]`, `[rest-docport]`, `[rest-protocol]`, and `[rest-execmode]` in lightningd [config](https://github.com/ElementsProject/lightning/blob/master/doc/lightningd-config.5.md)

E.g. add below to the `config` file in `.lightning` folder
```
plugin=/Users/<user>/c-lightning-REST/plugin.js
plugin=/Users/<user>/c-lightning-REST/clrest.js
rest-port=3002
rest-docport=4001
rest-protocol=https
Expand Down Expand Up @@ -128,13 +133,13 @@ Providing a `DOMAIN` to the c-lightning-REST configuration will add the domain a
If you are *upgrading* a server which is already configured, you should first backup and your entire `./certs` directory in case you need to restore it later.
Following this you should delete *only* the `.certs/certificate.pem` and `.certs/key.pem` files, so that new SSL certificates can be generated which take the `subjectAltName` into consideration.

**WARNING**: Do not delete `access.macaroon`. If you do then your connection to remote applications will be lost, and need to be re-configured.
**WARNING**: Do not delete `access.macaroon` or `rootKey.key`. If you do then your connection to remote applications will be lost, and need to be re-configured.

New certificates will be automatically generated as usual next time the program is started up.

### <a name="auth"></a>Authentication
Authentication has been implemented with macaroons. Macaroons are bearer tokens, which will be verified by the server.
A file `access.macaroon` will be generated in the `certs` folder in the application root.
Two files, `access.macaroon` and `rootKey.key`, will be generated in the `certs` folder in the application root.
The `access.macaroon` has to be read by the requesting application, converted to `base64` or `hex`, and passed in the header with key value `macaroon`.

Encoding Options for passing macaroon in the header:
Expand Down Expand Up @@ -179,7 +184,7 @@ C-Lightning commands covered by this API suite is [here](docs/CLTCommandCoverage
- disconnect (/v1/peer/disconnect) - `DEL`: Disconnect from a connected network peer
### Channel management
- fundchannel (/v1/channel/openChannel) - `POST`: Open channel with a connected peer node
- listchannels (/v1/channel/listChannels) - `GET`: Get the list of channels open on the node
- listchannels (/v1/channel/listChannels) - `GET`: Get the list of channels that are known to the node.
- setchannelfee (/v1/channel/setChannelFee) - `POST`: Update the fee policy for a channel
- close (/v1/channel/closeChannel) - `DEL`: Close channel
- listforwards (/v1/channel/listForwards) - `GET`: Get the list of forwarded htlcs by the node
Expand Down
13 changes: 8 additions & 5 deletions cl-rest.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const PORT = config.PORT;
const EXECMODE = config.EXECMODE;
const DOCPORT = config.DOCPORT;
const DOMAIN = config.DOMAIN || "localhost";
const BIND = config.BIND || "::";

//Create certs folder
try {
Expand All @@ -46,7 +47,7 @@ if ( ! fs.existsSync( key ) || ! fs.existsSync( certificate ) ) {
try {
execSync( 'openssl version', execOptions );
execSync(
`openssl req -x509 -newkey rsa:2048 -keyout ./certs/key.tmp.pem -out ${ certificate } -days 365 -nodes -subj "/C=US/ST=Foo/L=Bar/O=Baz/CN=c-lightning-rest" --addext "subjectAltName = DNS:${ DOMAIN }"`,
`openssl req -x509 -newkey rsa:2048 -keyout ./certs/key.tmp.pem -out ${ certificate } -days 365 -nodes -subj "/C=US/ST=Foo/L=Bar/O=Baz/CN=c-lightning-rest" -addext "subjectAltName = DNS:${ DOMAIN }"`,
execOptions
);
execSync( `openssl rsa -in ./certs/key.tmp.pem -out ${ key }`, execOptions );
Expand Down Expand Up @@ -134,13 +135,13 @@ try {
docserver = require( 'http' ).createServer( docapp );

//Start the server
server.listen(PORT, function() {
global.logger.warn('--- cl-rest api server is ready and listening on port: ' + PORT + ' ---');
server.listen(PORT, BIND, function() {
global.logger.warn('--- cl-rest api server is ready and listening on ' + BIND + ':' + PORT + ' ---');
})

//Start the docserver
docserver.listen(DOCPORT, function() {
global.logger.warn('--- cl-rest doc server is ready and listening on port: ' + DOCPORT + ' ---');
docserver.listen(DOCPORT, BIND, function() {
global.logger.warn('--- cl-rest doc server is ready and listening on ' + BIND + ':' + PORT + ' ---');
})

exports.closeServer = function(){
Expand All @@ -158,3 +159,5 @@ process.on('SIGTERM', () => {
docserver.close();
process.exit(0);
})

module.exports = { server, wsServer };
7 changes: 4 additions & 3 deletions plugin.js → clrest.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ restPlugin.addOption('rest-execmode', 'production', 'rest exec mode', 'string');
restPlugin.addOption('rest-rpc', ' ', 'allowed rpc commands', 'string');
restPlugin.addOption('rest-lnrpcpath', ' ', 'path for lightning-rpc', 'string');
restPlugin.addOption('rest-domain', ' ', 'domain name for self-signed cert', 'string');
restPlugin.addOption('rest-bind', ' ', 'Binding address', 'string');

restPlugin.onInit = params => {
process.env.LN_PATH = `${params.configuration['lightning-dir']}/${params.configuration['rpc-file']}`
Expand All @@ -24,11 +25,11 @@ restPlugin.onInit = params => {
RPCCOMMANDS: params.options['rest-rpc'].trim().split(",").map(s => s.trim()),
LNRPCPATH: params.options['rest-lnrpcpath'],
DOMAIN: params.options['rest-domain'].trim(),
BIND: params.options['rest-bind'].trim(),
PLUGIN: restPlugin
}

srvr = require('./cl-rest');

};

const EVENTS = [
Expand All @@ -44,9 +45,9 @@ const EVENTS = [
EVENTS.forEach(event => {
restPlugin.subscribe(event);
restPlugin.notifications[event].on(event, (msg) => {
if(srvr && srvr.broadcastToClients) {
if(srvr && srvr.wsServer && srvr.wsServer.broadcastToClients) {
updatedMessage = { event: event, data: msg };
srvr.broadcastToClients(updatedMessage);
srvr.wsServer.broadcastToClients(updatedMessage);
}
});
});
Expand Down
17 changes: 13 additions & 4 deletions controllers/channel.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ exports.openChannel = (req,res) => {
* tags:
* - Channel Management
* name: listchannel
* summary: Returns a list of channels on the node
* summary: Returns data on channels that are known to the node
* description: Core documentation - https://lightning.readthedocs.io/lightning-listchannels.7.html
* security:
* - MacaroonAuth: []
Expand Down Expand Up @@ -478,6 +478,10 @@ exports.listForwards = (req,res) => {
* name: maxLen
* description: maximum range after the offset you want to forward.
* type: integer
* - in: query
* name: sort_by
* description: Sort criteria, 'received_time' or 'resolved_time'.
* type: string
* security:
* - MacaroonAuth: []
* responses:
Expand Down Expand Up @@ -534,7 +538,7 @@ exports.listForwards = (req,res) => {
*/
exports.listForwardsPaginated = (req,res) => {
try {
var { status, offset, maxLen } = req.query;
var { status, offset, maxLen, sort_by } = req.query;
if (appCache.has('listForwards' + status)) {
global.logger.log('Reading ' + status + ' listForwards from cache');
var forwards = appCache.get('listForwards' + status);
Expand All @@ -547,7 +551,10 @@ exports.listForwardsPaginated = (req,res) => {
ln.listforwards(status=status).then(data => {
// Deleting failed and local_failed transactions after latest 1000 records
const forwards = !data.forwards ? [] : (req.query.status === 'failed' || req.query.status === 'local_failed') ? data.forwards.slice(Math.max(0, data.forwards.length - 1000), Math.max(1000, data.forwards.length)).reverse() : data.forwards.reverse();
// Caching data for subsequent pages
if (sort_by !== undefined) {
forwards.sort((a, b) => a[sort_by] - b[sort_by]);
}
// Caching data for subsequent pages
appCache.set('listForwards' + status, forwards);
res.status(200).json(getRequestedPage(forwards, offset, maxLen, status));
}).catch(err => {
Expand Down Expand Up @@ -599,6 +606,7 @@ getAliasForChannels = (peer) => {
our_channel_reserve_satoshis: channel.our_channel_reserve_satoshis,
spendable_msatoshi: channel.spendable_msatoshi,
funding_allocation_msat: channel.funding_allocation_msat,
opener: channel.opener,
direction: channel.direction
});
return acc;
Expand All @@ -623,6 +631,7 @@ getAliasForChannels = (peer) => {
our_channel_reserve_satoshis: channel.our_channel_reserve_satoshis,
spendable_msatoshi: channel.spendable_msatoshi,
funding_allocation_msat: channel.funding_allocation_msat,
opener: channel.opener,
direction: channel.direction
});
return acc;
Expand Down Expand Up @@ -818,4 +827,4 @@ exports.funderUpdate = (req,res) => {
res.status(500).json({error: err});
});
ln.removeListener('error', connFailed);
}
}
39 changes: 19 additions & 20 deletions controllers/invoice.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ var wsServer = require('../utils/webSocketServer');
* name: private
* description: Include routing hints for private channels (true or 1)
* type: string
* - in: body
* name: fallbacks
* description: The fallbacks array is one or more fallback addresses to include in the invoice (in order from most-preferred to least).
* type: array
* items:
* type: string
* - in: body
* name: preimage
* description: 64-digit hex string to be used as payment preimage for the created invoice. IMPORTANT> if you specify the preimage, you are responsible, to ensure appropriate care for generating using a secure pseudorandom generator seeded with sufficient entropy, and keeping the preimage secret. This parameter is an advanced feature intended for use with cutting-edge cryptographic protocols and should not be used unless explicitly needed.
* type: string
* security:
* - MacaroonAuth: []
* responses:
Expand All @@ -65,26 +75,15 @@ var wsServer = require('../utils/webSocketServer');
exports.genInvoice = (req,res) => {
function connFailed(err) { throw err }
ln.on('error', connFailed);
//Set required params
var amount = req.body.amount;
if(req.body.amount == 0)
amount = 'any';
var label = req.body.label;
var desc = req.body.description;
//Set optional params
var expiry = (req.body.expiry) ? req.body.expiry : null;
var exposePvt = (req.body.private === '1' || req.body.private === 'true') ? !!req.body.private : null;
//Set unexposed params
var fallback = null;
var preimage = null;

ln.invoice(msatoshi=amount,
label=label,
description=desc,
expiry=expiry,
fallback=fallback,
preimage=preimage,
exposeprivatechannels=exposePvt).then(data => {
ln.invoice(
msatoshi=((req.body.amount == 0) ? 'any' : req.body.amount),
label=req.body.label,
description=req.body.description,
expiry=(req.body.expiry || null),
fallbacks=(req.body.fallbacks || null),
preimage=(req.body.preimage || null),
exposeprivatechannels=(!!req.body.private || null)
).then(data => {
global.logger.log('bolt11 -> '+ data.bolt11);
global.logger.log('genInvoice success');
res.status(201).json(data);
Expand Down
12 changes: 3 additions & 9 deletions controllers/peers.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,7 @@ exports.listPeers = (req,res) => {
ln.listpeers().then(data => {
Promise.all(
data.peers.map(peer => {
peerData = {};
peerData = {
id: peer.id,
connected: peer.connected,
netaddr: peer.netaddr
};
return getAliasForPeer(peerData);
return getAliasForPeer(peer);
})
).then(function(peerList) {
res.status(200).json(peerList);
Expand Down Expand Up @@ -126,7 +120,7 @@ exports.listPeers = (req,res) => {
* parameters:
* - in: route
* name: pubKey
* description: Pubket of the connected peer
* description: Pubkey of the connected peer
* type: string
* required:
* - pubKey
Expand Down Expand Up @@ -184,4 +178,4 @@ getAliasForPeer = (peer) => {
resolve(peer);
});
});
}
}
Loading

0 comments on commit 2e01028

Please sign in to comment.