Andreas Brekken
Jan 17 · 5 min read

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:

$ 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:

/usr/local/bin/liquidd -> /home/ubuntu/liquid/bin/liquidd -> /home/ubuntu/liquid-3.14.1.21/bin/liquidd

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` 0014af097f4f55cc5245a9c71dc5f0d24be01e84b87305fcef878d6cb8bafc8e860ca687ec1ac56ace5e82bda2bd802b94e6a456550c

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)
  • 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.


SideShift AI is in its TEST PILOT STAGE. Want to become a TEST PILOT?

See sideshift.ai/pilot

SideShift AI

Development updates from SideShift AI

Andreas Brekken

Written by

SideShift AI

Development updates from SideShift AI

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade