Doppler – A Lightning Domain-Specific Language

Doppler – A Lightning Domain-Specific Language


October 11, 2023

The Problem

The Lightning Network, though not new, is continuously evolving, as are its developer tools. Developing apps on Lightning presents challenges not seen in conventional centralized payment systems. Unlike having a single software solution, the Lightning Network relies on technical guidelines named BOLTs. As a result, multiple software versions implement its protocol, with LND, CLN, Eclair, and LDK being the four primary ones. While all these implementations adhere to the BOLTs specification, BOLTs only outline the core essentials of the protocol. This results in each implementation having its unique features, leading to occasional interoperability issues. For example, an LND node might mistakenly deem a CLN node inactive when it's actually active.

The network's decentralized structure complicates the testing process for developers. That's where tools like Polar step in. Polar lets developers establish a local Lightning Network, set up nodes from various implementations, and execute basic tasks via a user interface, such as opening channels or making payments. While such tools are ideal during early development stages or for MVPs serving a limited audience, they can become challenging to utilize for testing as the application scales and user base expands.

A GUI isn't ideal for executing hundreds or thousands of tasks. Although developers can tap into the containers operating the nodes and run custom scripts for repeated or conditional actions, this presents challenges. Every implementation, be it LND, CLN, or Eclair, has its unique interface. A developer must craft three distinct scripts to execute the same task across these implementations.

At Voltage, our developers faced significant challenges. Our products interface directly with the Lightning Network. We provide nodes that allow users to operate their Lightning Nodes in the cloud, freeing them from the hassles of managing hardware and infrastructure. Surge offers valuable insights into the node internals, enabling businesses to fine-tune their Lightning Nodes and increase performance. Additionally, our LSP helps onboard thousands of users to the Lightning Network. Testing such applications was indeed a demanding task for our team.

The Solution

This is why we developed Doppler, a domain-specific language for the Lightning Network. At this point, you might ask yourself, "What is a domain-specific language?”. A Domain-Specific Language (DSL) is a specialized computer language tailored to a particular application domain. Unlike general-purpose languages, which are designed for writing software for many kinds of applications, a DSL is optimized for a specific set of tasks. It is often used to simplify complex operations within its domain.

Doppler is explicitly tailored for testing Lightning apps. It enables users to experiment with and test against various Lightning implementations. Whether it's for discovery testing, inclusion in a comprehensive integration testing suite, or simply investigating the interactions between different components. Internally, Doppler spins up a docker-compose cluster of docker containers. Each node is in it's container and they all communicate over the same docker network.. It’s like having Lego blocks to assemble as you need.

The application offers a robust set of features to streamline Lightning Network operations. It enables the creation of a Bitcoin-Core nodes cluster and provides the flexibility to designate one or multiple nodes as miners at specified intervals. Developers can set up and fund an LND nodes cluster backed by a chosen Bitcoin-Core node.

Moreover, Doppler facilitates the export of cluster configurations into docker-compose and ensures that all node logs and data are readily accessible. Customization is at the forefront with the ability to modify values in LND's configuration file and deterministically set up networking. Its command features are OPEN_CHANNEL, SEND_LN with various subcommands, SEND_ONCHAIN, LOOP commands over intervals, and CLOSE_CHANNEL. It supports multiple node implementations, including LND, CLN, and Eclair. Furthermore, Doppler also incorporates a cluster-level UI for enhanced visualization, allowing you to visualize the clusters you create.

Doppler is tailored to assist developers in testing Lightning apps of any size. For example, you could initiate 10 nodes from each implementation and send payments between them, be it through Lightning or on-chain, using a simple and short Doppler script. Even if the node implementations in your cluster differ, the same command works across all, as Doppler seamlessly manages the nuances, offering a streamlined testing interface. Oh, and it’s also open-source, of course.

Using Doppler

To use Doppler, ensure you have Rust and Docker installed on your computer. Clone the repository, cd into it, and then run cargo run --bin doppler -- -f "doppler_files/only_setup_network.doppler.

If you have an older version of docker-compose installed (the one called “docker-compose” instead of “docker-compose”), you might need to add the -d flag at the end of the previous prompt, like this `cargo run --bin doppler -- -f "doppler_files/only_setup_network.doppler" -d`

Now you can add a custom .doppler file to create a cluster how you want. You can check the example scripts here. You can also cd into the ui directory and run yarn && yarn dev to run the Blockly editor UI. After installing all the dependencies, you can access the UI through localhost:5173. More information about using Doppler can be found here. There you’ll find information about:

  • How to view logs of your container;
  • How to clear the docker cluster;
  • How to clear docker data;
  • Reset clusters;
  • How to test parse grammar;
  • Run Doppler in debug mode;
  • And more…

Going through an example script

Let’s go through a .doppler example:

BITCOIND_MINER bd1 10s // Defines a bitcoind (bd1) as a miner and finds a block every 10s
BITCOIND bd2 // Defines a bicoind node named bd2
BITCOIND bd3 // Defines a bitcoind node named bd2
LND lnd1 PAIR bd1 // Pairs an LND node, named lnd1, to bd1
LND lnd2 PAIR bd1 // Pairs an LND node, named lnd2, to bd1
LND lnd3 PAIR bd1 // Pairs an LND node, namede lnd3, to bd1
UP // Initiates the container

LOOP 2 EVERY 20s // Loops 2 times, with a 20s interval
  lnd1 OPEN_CHANNEL lnd2 AMT 500000 // Makes lnd1 open a channel with lnd2 with 500000 sats capacity
  lnd2 OPEN_CHANNEL lnd3 AMT 8000000 // Makes lnd2 open a channel with lnd3 with 8000000 sats capacity
  lnd3 OPEN_CHANNEL lnd1 AMT 900000 // Makes lnd3 open a channel with lnd1 with 900000 sats capacity
  lnd1 OPEN_CHANNEL lnd2 AMT 299999 // Makes lnd1 open a channel with lnd2 with 299999 sats capacity
  bd1 MINE_BLOCKS 10 // Makes bd1 mine 10 blocks
END // End the loop

// send on chain funds in the same pattern 3 times with no wait time
LOOP 3 // Loops 3 times with no intervals
    lnd1 SEND_ON_CHAIN lnd2 AMT 900 // Makes lnd1 send 900 BTC on chain to lnd2
    lnd3 SEND_ON_CHAIN lnd2 AMT 900 // Makes lnd3 send 900 BTC on chain to lnd2
    lnd2 SEND_ON_CHAIN lnd1 AMT 900 // Makes lnd3 send 900 BTC on chain to lnd1
    lnd2 SEND_ON_CHAIN lnd3 AMT 900 // Makes lnd2 send 900 BTC on chain to lnd3
END // End loop

LOOP EVERY 4s // Loop continuously every 4 seconds
  lnd2 SEND_LN lnd3 AMT 90 //  Makes lnd2 send 90 sats to lnd3
  lnd3 SEND_LN lnd2 AMT 90 // Makes lnd3 send lnd2 90 sats
  lnd1 SEND_LN lnd3 AMT 90 // Makes lnd1 send 90 sats to lnd3
  lnd3 SEND_LN lnd1 AMT 90 // Makes lnd3 send 90 sats to lnd3
  lnd2 SEND_LN lnd1 AMT 90 // Makes lnd2 send 90 sats to lnd1
  lnd1 SEND_LN lnd2 AMT 90 // Makes lnd1 send 90 sats to lnd2


The advent of the Lightning Network brought about a revolutionary approach to decentralized payment systems. Yet, as with most technological advancements, it posed its own set of unique challenges for developers. Issues ranging from software variations following BOLTs guidelines to interoperability challenges have necessitated the development of efficient testing tools for applications built on the Lightning Network. The creation of Doppler by Voltage’s developers is a testament to the evolving ecosystem and the innovation to address these challenges head-on.

Doppler, as a domain-specific language tailored for the Lightning Network, fills a significant gap in the developer toolkit. Its ability to streamline operations, from creating node clusters to executing payments, ensures robust application development. The fact that it allows for a uniform approach across different Lightning Network implementations further underscores its utility. Moreover, its open-source nature provides that the broader developer community can continually refine it, driving more robust and seamless interactions on the Lightning Network (contributions are welcomed!).

For developers grappling with the intricacies of Lightning app development, tools like Doppler pave the way for more efficient and effective testing. The example scripts elucidate the ease of executing complex operations, hinting at a brighter and more seamless future for Lightning Network application development. In summary, Doppler stands as a beacon of innovation, simplifying the intricate labyrinth of the Lightning Network for developers worldwide.

Get started building on Voltage today!

Share this post

Start Building on Bitcoin Now