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.
Please ensure you have installed the libsodium library for your platform. See install instructions [here](https://download.libsodium.org/doc/installation/index.html).
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, channel state and key generation for both parties.
use libbolt::bidirectional;
// setup bidirectional scheme params
let pp = bidirectional::setup(true);
// generate the initial channel state
// second argument represents third-party mode
let mut channel = bidirectional::ChannelState::new(String::from("My New Channel A"), false);
To generate keys for both parties, call the `bidirectional::keygen()` routine with the public parameters as input.
// merchant generates a long-lived key pair
let m_keypair = bidirectional::keygen(&pp);
// customer generates an ephemeral keypair for use on a single channel
let c_keypair = bidirectional::keygen(&pp);
### Initialization
To initialize the channel for both parties, do the following:
let b0_merch = 10;
let b0_cust = 100;
// initialize on the merchant side with balance, b0_merch
let mut m_data = bidirectional::init_merchant(&pp, b0_merch, &m_keypair));
// generate the public params for the commitment scheme
let cm_csp = bidirectional::generate_commit_setup(&pp, &m_keypair.pk);
// initialize on the customer side with balance, b0_cust
let mut c_data = bidirectional::init_customer(&pp, // public params
&channel, // channel state
b0_cust, // init customer balance
b0_merch, // init merchant balance
&cm_csp, // commitment pub params
&c_keypair)); // customer keypair
### Establish Protocol
When opening a payment channel, execute the establishment protocol API to escrow funds privately as follows:
// entering the establish protocol for the channel
let proof1 = bidirectional::establish_customer_phase1(&pp, &c_data, &m_data.bases);
// obtain the wallet signature from the merchant
let w_sig = bidirectional::establish_merchant_phase2(&pp, &mut channel, &m_data, &proof1));
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:
let pp = bidirectional::setup(true);
// create the channel state for each channel and indicate third-party support
let mut channel_a = bidirectional::ChannelState::new(String::from("Channel A -> I"), true);
let mut channel_b = bidirectional::ChannelState::new(String::from("Channel B -> I"), true);
Moreover, the intermediary can set a channel fee as follows:
channel_a.set_channel_fee(5);
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 (t_c1, new_w1, pay_proof1) = bidirectional::pay_by_customer_phase1(&pp, &channel_a,
&c1_data.channel_token, // channel token
&merch_keys.pk, // merchant pub key
&c1_data.csk, // wallet
payment_amount); // bal inc
// get payment proof on second channel with party B (and I)
let (t_c2, new_w2, pay_proof2) = bidirectional::pay_by_customer_phase1(&pp, &channel2,
&c2_data.channel_token, // channel token
&m_keys.pk, // merchant pub key
&c2_data.csk, // wallet
-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();