libbolt/README.md

313 lines
13 KiB
Markdown
Raw Normal View History

2018-02-15 21:00:07 -08:00
# libbolt
2018-04-02 07:48:01 -07:00
2018-07-23 23:40:13 -07:00
A pure-Rust library implementation of BOLT: Blind Off-chain Lightweight Transactions.
2018-04-02 07:48:01 -07:00
2018-08-16 23:00:02 -07:00
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.
2018-07-23 23:40:13 -07:00
# WARNING
2018-08-13 21:14:02 -07:00
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.
2018-07-23 23:40:13 -07:00
# NOTE
Active development of libbolt is ongoing at [Bolt Labs, Inc](https://github.com/boltlabs-inc/libbolt) to instantiate on a cryptocurrency. We will submit pull requests periodically when new features are complete.
2018-07-23 23:40:13 -07:00
# Dependencies
* secp256k1
2018-08-14 22:58:16 -07:00
* sodiumoxide
* pairing
* curve25519_dalek
* merlin
2018-07-23 23:40:13 -07:00
* bulletproofs
2018-08-14 23:04:44 -07:00
Note that the above rust dependencies will be compiled and installed as a result of running the `make` command.
2018-08-14 22:58:16 -07:00
# 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.
2018-08-14 10:12:28 -07:00
# Build & Install
2018-08-14 05:28:01 -07:00
Please ensure you have installed the libsodium library for your platform. See install instructions [here](https://download.libsodium.org/doc/installation/index.html).
2018-07-23 23:40:13 -07:00
2018-12-18 11:45:04 -08:00
To build the library and execute basic examples, run `make`
2018-07-23 23:40:13 -07:00
# Tests
2018-08-14 22:58:16 -07:00
To run libbolt unit tests, run `make test`
2018-07-23 23:40:13 -07:00
# Benchmarks
2018-08-14 22:58:16 -07:00
To run libbolt benchmarks, run `make bench`
2018-07-23 23:40:13 -07:00
# Usage
To use the libbolt library, add the `libbolt` crate to your dependency file in `Cargo.toml` as follows:
```toml
[dependencies]
bolt = "0.3.0"
2018-07-23 23:40:13 -07:00
```
Then add an extern declaration at the root of your crate as follows:
```rust
2018-12-18 11:45:04 -08:00
extern crate bolt;
2018-07-23 23:40:13 -07:00
```
# API
2018-08-16 23:00:02 -07:00
The libbolt library provides APIs for three types of payment channels:
2018-07-23 23:40:13 -07:00
2018-08-13 21:14:02 -07:00
* unidirectional payment channels (*work in progress*)
2018-08-16 23:00:02 -07:00
* bidirectional payment channels
* third-party payments
2018-07-23 23:40:13 -07:00
## Unidirectional Payment Channels
2018-08-14 23:04:44 -07:00
2018-08-24 00:31:46 -07:00
A unidirectional payment channel enables payments from a customer to a merchant and only supports transfer of fixed-sized values in one direction.
2018-08-14 23:04:44 -07:00
2018-08-24 00:18:36 -07:00
### Channel Setup and Key Generation
2018-08-24 00:31:46 -07:00
The first part of setting up unidirectional payment channels involve generating initial setup parameters, channel state and key generation for both parties.
2018-08-24 00:18:36 -07:00
2018-12-18 11:45:51 -08:00
use bolt::unidirectional;
2018-08-24 00:18:36 -07:00
// setup unidirectional scheme params
let pp = unidirectional::setup(true);
// generate the initial channel state
let mut channel = unidirectional::ChannelState::new(String::from("My New Channel A -> B"));
To generate keys for both parties, call the `unidirectional::keygen()` routine with the public parameters as input.
// merchant generates a long-lived key pair
let m_keypair = unidirectional::keygen(&pp);
// customer generates an ephemeral keypair for use on a single channel
let c_keypair = unidirectional::keygen(&pp);
### Initialization
To initialize the channel for both parties, do the following:
let b0_merch = 50;
let b0_cust = 50;
// initialize on the merchant side with balance, b0_merch
let mut m_data = unidirectional::init_merchant(&pp, b0_merch, &m_keypair));
// generate the public params for the commitment scheme
let cm_csp = unidirectional::generate_commit_setup(&pp, &m_keypair.pk);
// initialize on the customer side with balance, b0_cust
let mut c_data = unidirectional::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
**TODO**
### Pay protocol
**TODO**
### Channel Closure Algorithms
**TODO**
## 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, channel state and key generation for both parties.
2018-12-18 11:45:51 -08:00
use bolt::bidirectional;
// setup bidirectional scheme params
let pp = bidirectional::setup(true);
// generate the initial channel state
// second argument represents third-party mode
2018-08-24 00:18:36 -07:00
let mut channel = bidirectional::ChannelState::new(String::from("My New Channel A <-> B"), 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));
// complete channel establishment");
assert!(bidirectional::establish_customer_final(&pp, &m_keypair.pk, &mut c_data.csk, w_sig));
// confirm that the channel state is now established
assert!(channel.channel_established);
### Pay protocol
To spend on the channel, execute the pay protocol API (can be executed as many times as necessary):
// precomputation phase that customer does offline prior to a spend
bidirectional::pay_by_customer_phase1_precompute(&pp, &c_data.channel_token, &m_keypair.pk, &mut c_data.csk);
// generate new channel token, new wallet and payment proof
// send the payment proof to the merchant
let (t_c, new_w, pay_proof) = bidirectional::pay_by_customer_phase1(&pp, &channel,
&c_data.channel_token, // channel token
&m_keypair.pk, // merchant verification key
&c_data.csk, // current wallet
5); // balance increment
// get the refund token (rt_w) from the merchant
let rt_w = bidirectional::pay_by_merchant_phase1(&pp, &mut channel, &pay_proof, &m_data));
// generate the revocation token (rv_w) on the old public key (wpk)
let rv_w = bidirectional::pay_by_customer_phase2(&pp, &c_data.csk, &new_w, &m_keypair.pk, &rt_w));
// get the signature on the new wallet from merchant
let new_w_sig = bidirectional::pay_by_merchant_phase2(&pp, &mut channel, &pay_proof, &mut m_data, &rv_w));
// complete the final step of pay protocol - verify merchant signature on wallet
assert!(bidirectional::pay_by_customer_final(&pp, &m_keypair.pk, &mut c_data, t_c, new_w, new_w_sig));
### Channel Closure Algorithms
2018-08-16 23:00:02 -07:00
To close a channel, the customer must execute the `bidirectional::customer_refund()` routine as follows:
let cust_wallet = &c_data.csk;
let rc_c = bidirectional::customer_refund(&pp, &channel, &m_keypair.pk, &cust_wallet);
2018-08-16 23:00:02 -07:00
The merchant can dispute a customer's claim by executing the `bidirectional::merchant_retute()` routine as follows:
let channel_token = &c_data.channel_token;
let rc_m = bidirectional::merchant_refute(&pp, &mut channel, &channel_token, &m_data, &rc_c, &rv_w.signature);
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(&pp, &c_data, &m_data,
Some(rc_c), Some(rc_m), Some(rt_w));
`new_b0_cust` and `new_b0_merch` represent the new balances for the customer and merchant (respectively).
2018-08-24 00:18:36 -07:00
## Third-party Payments
2018-08-14 23:04:44 -07:00
2018-08-16 23:00:02 -07:00
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
2018-08-24 00:18:36 -07:00
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);
2018-08-16 23:00:02 -07:00
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();
assert!(bidirectional::verify_third_party_payment(&pp, tx_fee, &pay_proof1.bal_proof, &pay_proof2.bal_proof));
...
2018-08-24 00:18:36 -07:00
See the `third_party_payment_basics_work()` unit test in `src/lib.rs` for more details.
2018-08-14 05:28:01 -07:00
# Documentation
Build the api documentation by simply running `make doc`. Documentation will be generated in your local `target/doc` directory.
2018-08-14 22:58:16 -07:00
For the libbolt design documentation, see the `docs/bolt_design.pdf` document.
2018-08-14 05:28:01 -07:00
# Contributions
2018-08-14 22:58:16 -07:00
To contribute code improvements, please checkout the repository, make your changes and submit a pull request.
2018-08-14 05:28:01 -07:00
git clone https://github.com/ZcashFoundation/libbolt.git
2018-08-14 05:28:01 -07:00
# TODOs
Here are some TODOs (not in any particular order):
* Serialization support for libbolt structures such as `CustomerWallet`, `PaymentProof`, and so on.
* Support for other curves (e.g., pairing library from Zcash)
* Finish unidirectional channel construction
* Fix warnings
* Add more unit tests for other dispute resolution scenarios and pay protocol (to ensure appopriate aborts), third-party test cases, etc.
2018-08-14 05:28:01 -07:00
# License
2018-07-23 23:40:13 -07:00
2018-08-14 05:28:01 -07:00
Licensed under MIT (LICENSE-MIT or http://opensource.org/licenses/MIT)