CLN's Plugin Architecture

CLN's Plugin Architecture
Photo by Sigmund / Unsplash

C-Lightning (CLN) is a piece of software that allows your computer to communicate with bitcoin's lightning network... it's a lightning node. The team there has made a way for anyone to add custom functionality to their own node. This custom functionality is known as a plugin.

⚠️
Just about everything I am about to teach you was learned from Tony Aldon's amazing resource: lnroom.live

Running CLN

First, you will need to install the software. I recommend building from source, but all instructions can be found here.

💡
Farscapian has made this all very simple with the ROYGBIV Stack. This Docker stack will allow you to deploy Bitcoin Core and CLN with one simple script. Check out the docs.

Once installed, you can start your node with the lightningd command.

RPC Methods

CLN comes with a nice CLI that is used by running the lightning-cli command. From here, you are able to access all of the JSON RPC methods exposed by CLN.

💡
JSON RPC is a protocol for encoding messages and facilitating communication between client and server applications.

This is where it starts to get fun. Many RPC methods that can be used with your node are plugins. You can view the list of plugins here. There are also a bunch of community plugins you can use for added functionality.

For example, keysend is a method that can be used to send an unspecified amount of funds to another node using their node pubkey. Keysend is just a plugin and can be viewed here.

💡
To learn more about using custom plugins check out my post on starting the prism plugin on your node.

How Plugins Work

"A plugin may be written in any language, and communicates with lightningd through the plugin's stdin and stdout." - CLN docs

Get Manifest

When a plugin is started, it gets registered with `lightningd` through the getmanifest request. This request gets sent to your plugin's standard input (stdin) and a response is expected from the plugin's standard output (stdout).

The getmanifest request looks something like this:

{
  "jsonrpc": "2.0",
  "id": 86,
  "method": "getmanifest",
  "params": {
    "allow-deprecated-apis": false
  }
}

And the expected response looks something like this:

{
    "jsonrpc": "2.0",
    "id": req_id,
    "result": {
        "dynamic": True,
        "options": [{
            "name": "foo_opt",
            "type": "string",
            "default": "bar",
            "description": "description"
        }],
        "rpcmethods": [{
            "name": "myplugin",
            "usage": "",
            "description": "description"
        }]
    }
}

Init

After getmanifest, lightningd will send the init request. This request provides important information about the node such as the lightning-dir used for accessing RPC methods.

The expected response to the init request looks like:

{
    "jsonrpc": "2.0",
    "id": req_id,
    "result": {}
}
💡
To learn more about building plugins check out "Understand CLN Plugin mechanism with a Python example" by Tony Aldon

Input Output Communication

Once the plugin is registered by lightningd, the input-output loop can start. Whenever a method defined in the plugin is called, lightningd will send that request to the plugin's stdin and will receive and response through the plugin's stdout.

Conclusion

Plugins are subprocesses of the lightning daemon. Much of the out-of-box functionality in CLN is included as plugins, but any user is free to add plugins of their choosing.

This plugin architecture allows for a rich set of features to exist on CLN and is why we decided to implement BOLT 12 prisms as a CLN plugin.

gudnuf

gudnuf

developing = building + learning