Blockstream’s Liquid product is a fork of Bitcoin that replaces the consensus model from proof-of-work to a federated consensus model. Most users are familiar with the federated consensus model from other payment networks such as Ripple.

Bitfinex and BitMEX were announced by Blockstream as partnering exchanges, but I was unable to find deposit/withdrawal of L-BTC on either exchange. Perhaps SideShift AI will be the first to integrate Liquid.

Live demonstration of a Shift of BTC from Bitcoin Lightning to Liquid.

Instance specification

I deploy a Ubuntu 18.04 instance on Amazon AWS with these modest specs:

t2.smal (1 vCPU, 2 GB RAM)

OS volume: 20 GB SSD

Data volume: 250 GB SSD

The reason for the low specs is that Liquid is new and won’t have to deal with a large mempool or transaction throughput.

I habitually use a separate volume for the node data, which includes configuration file, blockchain data, wallet data. This allows me to easily switch over to a new machine if the OS should suffer a catastrophic event.

Installation

Liquid requires both a liquidd node and a bitcoind node. This is because Liquid is a sidechain that’s able to receive BTC from the Bitcoin chain and return BTC to the Bitcoin chain.

Over at the releases page on the Liquid Github I find the latest release, v3.14.1.21, download and extract it:



$ tar zxf liquid*.tar.gz

$ ln -s `realpath liquid-3.14.1.21` `realpath liquid`

$ pushd /usr/local/bin

$ sudo ln -s /home/ubuntu/liquid/bin/* . $ wget https://github.com/Blockstream/liquid/releases/download/liquid.3.14.1.21/liquid-3.14.1.21-x86_64-linux-gnu.tar.gz $ tar zxf liquid*.tar.gz$ ln -s `realpath liquid-3.14.1.21` `realpath liquid`$ pushd /usr/local/bin$ sudo ln -s /home/ubuntu/liquid/bin/* .

I’ve now created symbolic links like this:

This symlink chain makes it convenient to upgrade Liquid in the future. I just need to replace the link to /home/ubuntu/liquid .

I replace this procedure for the latest version of Bitcoin Core, such that /usr/local/bin/bitcoind links to /home/ubuntu/bitcoin-0.17.0/bin .

For both bitcoind and liquidd to start automatically, I create two systemd unit files; bitcoind.servivce and liquidd.service.

You can see in the systemd unit files that bitcoind and liquidd have their data directories set to /opt/bitcoin and /opt/liquid respectively. The /opt directory is the data volume I described previously.

Configuration files

The Bitcoin configuration file, /opt/bitcoin/bitcoin.conf is quite straight forward:

rpcuser=user

rpcpassword=santa

rpcallowip=0.0.0.0/0

txindex=1

printtoconsole=1

server=1

The Liquid daemon must be able to speak to the Bitcoin daemon, which we configure in /opt/liquid/liquid.conf :

rpcuser=user

rpcpassword=claus

rpcallowip=0.0.0.0/0

txindex=1

printtoconsole=1

mainchainrpchost=127.0.0.1

mainchainrpcuser=user

mainchainrpcpassword=santa

mainchainrpcport=8332

rpcport=8432

Liquid is now able to speak to Bitcoin over RPC.

Starting the instances

I first enable and start the bitcoind system service:

$ sudo systemctl enable bitcoind

$ sudo systemctl start bitcoind

$ sudo systemctl status bitcoind

● bitcoind.service - Bitcoin Daemon

Loaded: loaded (/etc/systemd/system/bitcoind.service; enabled; vendor preset: enabled)

Active: active (running) since Mon 2018-11-12 01:05:18 UTC; 1 day ago

Main PID: 1624 (bitcoind)

Tasks: 13 (limit: 2362)

CGroup: /system.slice/bitcoind.service

└─1624 /usr/local/bin/bitcoind -datadir=/opt/bitcoin Jan 17 20:49:46 sideshift-liquid bitcoind[1624]: 2019-01-17T20:49:46Z Pre-allocating up to position 0x1000000 in blk01498.dat

Jan 17 20:49:46 sideshift-liquid bitcoind[1624]: 2019-01-17T20:49:46Z Pre-allocating up to position 0x100000 in rev01498.dat

and for the liquid service:

$ sudo systemctl enable liquidd

$ sudo systemctl start liquidd

$ sudo systemctl status liquidd

● liquidd.service - Liquid Daemon

Loaded: loaded (/etc/systemd/system/liquidd.service; enabled; vendor preset: enabled)

Active: active (running) since Mon 2018-11-12 01:07:30 UTC; 1 day ago

Main PID: 1766 (liquidd)

Tasks: 14 (limit: 2362)

CGroup: /system.slice/liquidd.service

└─1766 /usr/local/bin/liquidd -datadir=/opt/liquid Jan 17 22:01:36 sideshift-liquid liquidd[1766]: 2019-01-17 22:01:36 UpdateTip: new best=f3a5b642f9e0347642c3a4412d4f7425f1e97fd3e3a5600e1ca45d38a92773d5 height=142622 version=0x20000000 log2_work=17.121

Obtaining some L-BTC

The native currency of the Liquid network is L-BTC , which means BTC that is stored in the Liquid sidechain. We could have a friend send us some L-BTC , buy it on an exchange, or send from the Bitcoin network using the peg-in process. The latter is obviously cooler.

To make my life a little easier, create these two aliases in my shell:

alias btc="bitcoin-cli -datadir=/opt/bitcoin"

alias lq="liquid-cli -datadir=/opt/liquid"

I generate a new Bitcoin address:

$ btc getnewaddress

3GDctGL32v4Mt8GRqQsjA44aw7o2DVsRV6

And I send it 0.02669942 BTC (around $100). Storing the funds using a Bitcoin Core wallet will make this process much simpler.

We then obtain a peg-in address for Liquid:

$ lq getpeginaddress

{

"mainchain_address": "31oQLrR1qeGSdJxFMeTVuXkqxjd9gJ1E6s",

"claim_script": "0014af097f4f55cc5245a9c71dc5f0d24be01e84b873"

}

And send the funds to the peg-in address:

$ btc sendtoaddress 31oQLrR1qeGSdJxFMeTVuXkqxjd9gJ1E6s `btc getbalance` "" "" true

8954038936ec3d96a283fd7e5336ec17e4ad06876ad2a765ceef31778f70a5b0

This transaction is the peg-in transaction. We’ll need its raw transaction data to claim the peg-in transaction later:

$ btc getrawtransaction 8954038936ec3d96a283fd7e5336ec17e4ad06876ad2a765ceef31778f70a5b0 > tx.txt

And the transaction proof

btc gettxoutproof '["8954038936ec3d96a283fd7e5336ec17e4ad06876ad2a765ceef31778f70a5b0"]' > proof.txt

There’s quite a few strings to deal with now, and we’ll need to use them when we claim the peg-in transaction. But there’s catch! We’ll need to wait for 102 confirmations (~17 hours) to be able to claim the peg-in.

+----------------+----------------------------------------------+

| Name | Value |

+----------------+----------------------------------------------+

| Peg-in address | 31oQLrR1qeGSdJxFMeTVuXkqxjd9gJ1E6s |

| Claim-script | 0014af097f4f55cc5245a9c71dc5f0d24be01e84b873 |

| Peg-in tx hash | 8954038936ec3d96a283fd7e5336ec17e4ad06876... |

| Peg-in tx proof| Stored in proof.txt |

| Peg-in tx raw | Stored in tx.txt |

+----------------+----------------------------------------------+

102 confirmations later

We can now claim the peg-in transaction.

$ lq claimpegin `cat tx.txt` `cat proof.txt` 0014af097f4f55cc5245a9c71dc5f0d24be01e84b873 05fcef878d6cb8bafc8e860ca687ec1ac56ace5e82bda2bd802b94e6a456550c

After a few minutes we can verify that the L-BTC was received.

$ lq getbalance

{

"bitcoin": 0.02669942

}

Experienced bitcoind users will notice that getbalance returns key-values instead of just a number. This is because Liquid supports issuing custom tokens, like you’re probably used to with ERC20s. A major difference is that Liquid uses a technology called Confidential Assets, which provides privacy.

You can read more about Confidential Assets in its whitepaper.

Integrating sending/receiving payments

SideShift AI will support only the native L-BTC token until some interesting assets become available on the Liquid network. Perhaps we should issue our SAI token as an asset on Liquid?

Integration work for L-BTC is identical to that of Bitcoin:

Receiving funds

for every new block with at least 1 confirmation

for every transaction in that block

for every output in that transaction

- Was it sent to a SideShift AI deposit address?

- Credit the user unless it has previously been credited

Sending funds

Use the sendtoaddress RPC call, or sendtomany if using batching.

Notable differences from Bitcoin

getbalance RPC call returns a hashmap (currency->balance)

RPC call returns a hashmap (currency->balance) getnewaddress RPC call returns a bech32 address. Can be converted to old-school using validateaddress RPC call.

Closing remarks

Integrating Liquid and pegging in was easier than expected and easily manageable for a developer experienced with Bitcoin. I’m curious to see how integrating Confidential Assets will differ.