Skip to content
Rust implementation of libbolt
C++ Rust Python C Go Makefile
Branch: master
Clone or download
Pull request Compare This branch is 214 commits ahead, 1 commit behind ZcashFoundation:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.
cpp Update example for cpptest Sep 14, 2019
examples Cleaning up warnings in addition to establish interface and c/py/go b… Sep 16, 2019
go Sync Rust bolt api with Go Sep 16, 2019
include Cleaning up warnings in addition to establish interface and c/py/go b… Sep 16, 2019
py Fix test Sep 17, 2019
src Fix test Sep 17, 2019
.gitignore fix some warnings Aug 30, 2019
.travis.yml add travis config Jul 25, 2018
Cargo.toml Clean up deps Sep 12, 2019
LICENSE Initial commit Feb 16, 2018
Makefile Update example for cpptest Sep 14, 2019 Sync Rust bolt api with Go Sep 16, 2019


A pure-Rust library implementation of BOLT: Blind Off-chain Lightweight Transactions.

BOLT is a system for conducting privacy-preserving off-chain payments between pairs of individual parties. BOLT is designed to provide a Layer 2 payment protocol for privacy-preserving cryptocurrencies such as Zcash, by allowing individuals to establish and use payment channels for instantaneous payments that do not require an on-chain transaction.


The libbolt library is a proof of concept implementation that relies on experimental libraries and dependencies at the moment. It is not suitable for production software yet.


Active development of libbolt is ongoing at Bolt Labs, Inc to instantiate on a cryptocurrency. We will submit pull requests periodically when new features are complete.


  • secp256k1
  • sodiumoxide
  • pairing

Note that the above rust dependencies will be compiled and installed as a result of running the make command.

Rust Nightly Setup

Please keep in mind we are currently working with nightly Rust for now which gives access to the nightly compiler and experimental features.

rustup install nightly

To run a quick test of the nightly toolchain, run the following command:

rustup run nightly rustc --version

Optionally, to make this the default globally, run the following command:

rustup default nightly

We will switch to the stable release channel once libbolt (and dependencies) are ready for production use.

Build & Install

Please ensure you have installed the libsodium library for your platform. See install instructions here.

To build the library and execute basic examples, run make


To run libbolt unit tests, run make test


To run libbolt benchmarks, run make bench


To use the libbolt library, add the libbolt crate to your dependency file in Cargo.toml as follows:

bolt = "0.3.0"

Then add an extern declaration at the root of your crate as follows:

extern crate bolt;


The libbolt library provides APIs for two types of payment channels:

  • bidirectional payment channels
  • third-party payments

Bidirectional Payment Channels

A bidirectional payment channel enables two parties to exchange arbitrary positive and negative amounts.

Channel Setup and Key Generation

The first part of setting up bi-directional payment channels involve generating initial setup parameters using curve BLS12-381 with channel state.

use bolt::bidirectional;
// generate the initial channel state 
// second argument represents third-party mode
let mut channel_state = bidirectional::ChannelState::<Bls12>::new(String::from("Channel A -> B"), false);
let mut rng = &mut rand::thread_rng();

// generate fresh public parameters
channel_state.setup(&mut rng); 


To initialize state/keys for both parties, call the bidirectional::init_merchant() and bidirectional::init_customer():

let b0_merch = 10;
let b0_cust = 100;

// initialize the merchant state and initialize with balance
let (mut channel_token, mut merch_state, mut channel_state) = bidirectional::init_merchant(rng, &mut channel_state, "Bob");
// generate the customer state using the channel token from the merchant
let mut cust_state = bidirectional::init_customer(rng, // rng
                                              &mut channel_token, // channel token
                                              b0_cust, // init customer balance
                                              b0_merch, // init merchant balance
                                              "Alice")); // channel name/purpose

Establish Protocol

When opening a payment channel, execute the establishment protocol API to escrow funds privately as follows:

// establish the channel by generating initial state commitment proof
let (com, com_proof) = bidirectional::establish_customer_generate_proof(rng, &mut channel_token, &mut cust_state);

// obtain close token for closing out channel
let close_token = bidirectional::establish_merchant_issue_close_token(rng, &channel_state, &com, &com_proof, &merch_state);

// customer verifies that close-token
assert!(cust_state.verify_close_token(&channel_state, &close_token));

// form funding tx and wait for network confirmation

// obtain payment token after confirming funding tx
let pay_token = bidirectional::establish_merchant_issue_pay_token(rng, &channel_state, &com, &merch_state);
// customer 
assert!(bidirectional::establish_final(&mut channel_state, &mut cust_state, &pay_token));   
// confirm that the channel state is now established

Pay protocol

To spend on the channel, execute the pay protocol API (can be executed as many times as necessary):

// phase 1 - payment proof and new cust state
let (payment, new_cust_state) = bidirectional::generate_payment_proof(rng, &channel_state, &cust_state, 10);

// phase 1 - merchant verifies the payment proof and returns a close-token   
let new_close_token = bidirectional::verify_payment_proof(rng, &channel_state, &payment, &mut merch_state);

// phase 2 - verify the close-token, update cust state and generate a revoke token for previous cust state state
let revoke_token = bidirectional::generate_revoke_token(&channel_state, &mut cust_state, new_cust_state, &new_close_token);

// phase 2 - merchant verifies the revoke token and sends back the pay-token in response
let new_pay_token = bidirectional::verify_revoke_token(&revoke_token, &mut merch_state);

// final - customer verifies the pay token and updates internal state
assert!(cust_state.verify_pay_token(&channel_state, &new_pay_token));

Channel Closure Algorithms

To close a channel, the customer must execute the bidirectional::customer_refund() routine as follows:

let cust_close_msg = bidirectional::customer_close(&channel_state, &cust_state);

If the customer broadcasts an outdated version of his state, then the merchant can dispute this claim by executing the bidirectional::merchant_retute() routine as follows:

let merch_close = bidirectional::merchant_close(&channel_state, &channel_token, &cust_close_msg, &merch_state);

To resolve a dispute between a customer and a merchant, the following routine is executed by the network:

let (new_b0_cust, new_b0_merch) = bidirectional::resolve(...);

new_b0_cust and new_b0_merch represent the new balances for the customer and merchant (respectively).

Third-party Payments

The bidirectional payment channels can be used to construct third-party payments in which a party A pays a second party B through an untrusted intermediary (I) to which both A and B have already established a channel. With BOLT, the intermediary learns nothing about the payment from A to B and cannot link transactions to individual users.

To enable third-party payment support, initialize each payment channel as follows:

// create the channel state for each channel and indicate third-party support 
let mut channel_a = bidirectional::ChannelState::<Bls12>::new(String::from("Channel A <-> I"), true);
let mut channel_b = bidirectional::ChannelState::<Bls12>::new(String::from("Channel B <-> I"), true);

Moreover, the intermediary can set a channel fee as follows:


The channel establishment still works as described before and the pay protocol includes an additional step to verify that the payments on both channels cancel out or include a channel fee (if specified).


let payment_amount = 20;
// get payment proof on first channel with party A (and I)
let (payment_proofA, new_cust_stateA) = bidirectional::generate_payment_proof(rng, &channel_a, // channel state
                                                                    payment_amount); // bal inc
// get payment proof on second channel with party B (and I)
let (payment_proofB, new_cust_stateB) = bidirectional::generate_payment_proof(rng, &channel_b,
                                                                    -payment_amount); // bal dec
// verify that the payment proof is valid and cancels out or results in a fee
let tx_fee = channel_a.get_channel_fee() + channel_b.get_channel_fee();
assert!(bidirectional::verify_third_party_payment(&pp, tx_fee, &payment_proofA, &payment_proofB));


See the third_party_payment_basics_work() unit test in src/ for more details.

Documentation (TODO)

Build the api documentation by simply running make doc. Documentation will be generated in your local target/doc directory.

For the libbolt design documentation, see the docs/bolt_design.pdf document.


To contribute code improvements, please checkout the repository, make your changes and submit a pull request.

git clone


Here are some TODOs (not in any particular order):

  • Fix warnings
  • Add more unit tests for other dispute resolution scenarios and third-party test cases


Licensed under MIT (LICENSE-MIT or

You can’t perform that action at this time.