Liquid Bitcoin (L-BTC) Node for CAS
GENERAL BYTES incorporated support for the Liquid Network in CAS version 20250901.
“The Liquid Network is an open-source Bitcoin sidechain and layer-2 solution interoperable with Lightning that enables faster, more confidential bitcoin transactions and the issuance and exchange of digital assets like stablecoins, tokenized securities, and bonds.”
More information from: https://liquid.net/
Table of Contents
Overview
Providing Liquid Bitcoin (L_BTC) on your BATMs requires the following steps:
Install a Bitcoin Core node.
Wait for the Bitcoin Core node to sync with Bitcoin network.
Install the Elements node and connect it to Bitcoin Core.
Fund your node.
Enable secure connection between you CAS and the Elements node.
Configure the “Liquid Network Bitcoin - Elements Core” Crypto Setting.
Install Bitcoin Core
Instructions: https://generalbytes.atlassian.net/wiki/x/2oDoO
The Bitcoin Core node must be fully synced and operational before proceeding to install Elements. This may take days, or even a week - depending upon your system configuration and network speed.
Elements node installation
Install Ubuntu 24.04 or newer. Running bitcoind and elementsd at the same time requires 16 GB of RAM and will consume (as of October 2025) at least 1 TB of drive space.
Download release for Linux x64 from here: https://github.com/ElementsProject/elements/releases . At the time of this article creation latest release file was
elements-23.3.0-x86_64-linux-gnu.tar.gz.
wget https://github.com/ElementsProject/elements/releases/download/elements-23.3.0/elements-23.3.0-x86_64-linux-gnu.tar.gz
tar -xzvf elements-23.3.0-x86_64-linux-gnu.tar.gzRun elementsd
cd elements-23.3.0/bin
./elementsdWait for elements to synchronize - this may take 2+ days.
Create your first elements wallet:
./elements-cli createwallet mainCheck that wallet was properly created
./elements-cli -rpcwallet=main getwalletinfo
{
"walletname": "main",
"walletversion": 169900,
"format": "bdb",
"balance": {
"bitcoin": 0.00000000
},
"unconfirmed_balance": {
"bitcoin": 0.00000000
},
"immature_balance": {
"bitcoin": 0.00000000
},
"txcount": 0,
"keypoololdest": 1754416920,
"keypoolsize": 1000,
"hdseedid": "c0e448000c131135c89f777d6632dc729dcbe80e",
"keypoolsize_hd_internal": 1000,
"paytxfee": 0.00000000,
"private_keys_enabled": true,
"avoid_reuse": false,
"scanning": false,
"descriptors": false,
"external_signer": false
}View the current receiving addresses of our main wallet:
./elements-cli -rpcwallet=main listreceivedbyaddressExample response (it will be empty as there is no wallet yet):
[
]Get your first new address. This L-BTC address is where we will receive our L-BTC:
./elements-cli getnewaddressExample response:
lq1qqdy4kz0p9k05mgzlv2eu7l0nzfzka7n5el9txgxx7ps6fldvtx2x6gj4ual0kxhfzruc39e9pf9f5gqm9vfqzskwl4xdetjypFirst create a pegin bitcoin wallet on your node where you will be receiving the BTC that will be converted to L-BTC. Run the following command on your Bitcoin node:
./bitcoin-cli createwallet peginTypical result:
{
"name": "pegin"
}Get your first pegin address:
./elements-cli getpeginaddressExample response:
{
"mainchain_address": "bc1qhhvyluwua7552wqhjv23xt5pdnvlumqmad0ngkwtg7whtrn4hh8sfwhpc3",
"claim_script": "00141923225c399212b8772dc594d2c70af143b01a10"
}Now you can send your BTC (start with small amount first) to a pegin address (in our case it was
bc1qhhvyluwua7552wqhjv23xt5pdnvlumqmad0ngkwtg7whtrn4hh8sfwhpc3).In our example the transfer was performed in transaction:
240e62ef23fa4c3837e17e578c07b6a71d2131b0dde15762403d4c81a60f0e8e.
You must wait for 100 confirmations (about 16 hours) for the BTC to be pegged.
Get the raw transaction. When you don’t have
txindex=1uncommented in bitcoin.conf then you need to also provide format(0) and blockhash of block in which was transaction included. In your example transaction240e62ef23fa4c3837e17e578c07b6a71d2131b0dde15762403d4c81a60f0e8ewas included in block#908772that has this blockhash:00000000000000000001c272398a39820e1a3feb9a153fb2eb44db5dc51189cb.
./bitcoin-cli getrawtransaction 240e62ef23fa4c3837e17e578c07b6a71d2131b0dde15762403d4c81a60f0e8e 0 00000000000000000001c272398a39820e1a3feb9a153fb2eb44db5dc51189cbExample response:
02000000016132a5b22818d229b345c24613592285a24d77c14b3a01e9aaa3e2cd63935318000000006a47304402206ae69b9d99c63e27b751392cb933fa9cfd42ae1c93dd820e911fa20ddca90e2502206d15ca0ae3c12e1f3f3c52c45f2c27a5a995b167cdc00794522cf7f8903e261e012103967318c3e5e5a4c36e4f874077d4b5d3cbd372473db31e12a2d9de286e4be82cfdffffff01c344000000000000220020bdd84ff1dcefa94538179315132e816cd9fe6c1beb5f3459cb479d758e75bdcf00000000Once you have a raw transaction then you can generate a “txoutproof”. gettxoutproof produces a Merkle proof that shows your transaction is included in a specific Bitcoin block:
./bitcoin-cli gettxoutproof '["240e62ef23fa4c3837e17e578c07b6a71d2131b0dde15762403d4c81a60f0e8e"]' 00000000000000000001c272398a39820e1a3feb9a153fb2eb44db5dc51189cbExample response:
0000ff3f4d27d84a694c25d27c81eafbea0425769b7cbf61ec2c000000000000000000003b0fd83de1343e4f7c7e3f3f4ee017af99992852503ca3fb0c313c60579f2717bb5a92689e3402177aee7e5e550300000bec7a16609482bf507980c0c8f36dfb48d94514e5da8925168fca92f8c0138a4d1ee08c837336e8805fca007cea9381a95ce0df34d3888beddfd20c233151c4a1ec672a1ffd29ca5df057b45adb2f6cc58f294b72163d106a509d00a3d667a0218e0e0fa6814c3d406257e1ddb031211da7b6078c577ee137384cfa23ef620e248562cc7b57983a85284a102acfcedbb7796dd7f14fd2d3b678aafbf966604b5f875cc5b5d886fa4ccdce20624815bc500f97d6a80aa7ecd002a0c000d80b36eaace40794842ce47d094f5901de44fdf949729e28c10a71c1e299dc8119f019ab449bfcfff676e3ca01896b8b03129d5d6a53e364e66bf5d6b7d6551bb9c5427c7a8954a8d9f5cfcf676cadca3d11548492697dd37d662d2733ff1d6349d12d07ab52b2284a7b362b923274b05c0d719c3ac12fa334109d3805b800d793b5df426aeb5dfd8ccdc2bc0da9db8af315ec7ac776d2b358531c0c3da2ba23a6d4918003ef2b00Claim Liquid bitcoin on our elements node. We will provide the rawtxoutput which was used to fund the wallet, a proof that the transaction was included to a block and a claim script. Note that we needed to add as a third parameter a claimscript that elementsnode returned when it generated the address for us in previous step. Returned value is a txid on liquid chain.
./elements-cli claimpegin 02000000016132a5b22818d229b345c24613592285a24d77c14b3a01e9aaa3e2cd63935318000000006a47304402206ae69b9d99c63e27b751392cb933fa9cfd42ae1c93dd820e911fa20ddca90e2502206d15ca0ae3c12e1f3f3c52c45f2c27a5a995b167cdc00794522cf7f8903e261e012103967318c3e5e5a4c36e4f874077d4b5d3cbd372473db31e12a2d9de286e4be82cfdffffff01c344000000000000220020bdd84ff1dcefa94538179315132e816cd9fe6c1beb5f3459cb479d758e75bdcf00000000 0000ff3f4d27d84a694c25d27c81eafbea0425769b7cbf61ec2c000000000000000000003b0fd83de1343e4f7c7e3f3f4ee017af99992852503ca3fb0c313c60579f2717bb5a92689e3402177aee7e5e550300000bec7a16609482bf507980c0c8f36dfb48d94514e5da8925168fca92f8c0138a4d1ee08c837336e8805fca007cea9381a95ce0df34d3888beddfd20c233151c4a1ec672a1ffd29ca5df057b45adb2f6cc58f294b72163d106a509d00a3d667a0218e0e0fa6814c3d406257e1ddb031211da7b6078c577ee137384cfa23ef620e248562cc7b57983a85284a102acfcedbb7796dd7f14fd2d3b678aafbf966604b5f875cc5b5d886fa4ccdce20624815bc500f97d6a80aa7ecd002a0c000d80b36eaace40794842ce47d094f5901de44fdf949729e28c10a71c1e299dc8119f019ab449bfcfff676e3ca01896b8b03129d5d6a53e364e66bf5d6b7d6551bb9c5427c7a8954a8d9f5cfcf676cadca3d11548492697dd37d662d2733ff1d6349d12d07ab52b2284a7b362b923274b05c0d719c3ac12fa334109d3805b800d793b5df426aeb5dfd8ccdc2bc0da9db8af315ec7ac776d2b358531c0c3da2ba23a6d4918003ef2b00 00141923225c399212b8772dc594d2c70af143b01a10Example response:
20ea7b89adbf0c4aab3bb7b4d7b42dd3063f4cd1076bba64c8c24f21c4f22dc6Check your balance. BTC should now be listed. Type this:
./elements-cli getwalletinfoThis is a typical response:
{
"walletname": "main",
"walletversion": 169900,
"format": "bdb",
"balance": {
"bitcoin": 0.00017565
},
"unconfirmed_balance": {
"bitcoin": 0.00000000
},
"immature_balance": {
"bitcoin": 0.00000000
},
"txcount": 1,
"keypoololdest": 1754416920,
"keypoolsize": 999,
"hdseedid": "c0e448000c131135c89f777d6632dc729dcbe80e",
"keypoolsize_hd_internal": 1000,
"paytxfee": 0.00000000,
"private_keys_enabled": true,
"avoid_reuse": false,
"scanning": false,
"descriptors": false,
"external_signer": false
}Setup a secure tunnel for encrypted communication.
Your CAS server and this node must have a secure line. Your password and other sensitive information will be passed back & forth. Encrypt (and thus protect) this communication by using a secure SSH tunnel.
The GB Wallet Tunnel is recommended.
General Bytes has incorporated an open-source SSH client into CAS.
Click here for instructions to install the GB Wallet Tunnel Server on this node.
Alternative (unsupported):
Build an SSH tunnel (instead of the GB Wallet Tunnel), see: https://generalbytes.atlassian.net/l/cp/b7j5AVHA
With those instructions,
set
FORWARDED_PORT=8332for Bitcoin Core, and using the script again,set
FORWARDED_PORT=7042for the Liquid Network Elements Node.
Connect Liquid Network Node in CAS
Once you have the Liquid node installed, synchronized, have a balance in it, and the node is accessible via the GB Wallet Tunnel - configure CAS to connect to your node.
Enabling RPC on node
Before configuring CAS we need to make sure that the RPC (Remote Procedure Call) of your elementsd node:
requires a username and password (choose wisely),
listens on the correct IP address (rpcbind),
You may permit multiple
rpcbindentries as needed.
and accepts connections only from permitted IP addresses.
You may specify multiple
rpcallowipentries if needed.
DO NOT allow/specify public IP addresses!
Add the following lines into your ~/.elements/elements.conf file. Make sure you choose a different password and username. If the file doesn’t exist you will need to create it:
sudo nano ~/.elements/elements.confExample settings for the file ~/.elements/elements.conf:
server=1 # enable RPC server
txindex=1
rpcuser=myuser
rpcpassword=myPAZs2345x!2
rpcbind=127.0.0.1
rpcallowip=127.0.0.1Use Ctrl+X to save the file, and
then restart
elementsdto have the new settings take effect.
You can test that your RPC is configured properly by running the following line:
curl --user myuser:myPAZs2345x!2 --data-binary '{"jsonrpc":"1.0","id":"curl","method":"getblockchaininfo","params":[]}' -H 'content-type:text/plain;' http://127.0.0.1:7041/Replace
myuser:myPAZs2345x!2with your actual username and password.
To check the balance you can run this line:
curl --user myuser:myPAZs2345x!2 --data-binary '{"jsonrpc":"1.0","id":"curl","method":"getbalance","params":["main"]}' -H 'content-type:text/plain;' http://127.0.0.1:7041/Make sure you have your wallet loaded when calling the RPC.
Load the wallet by calling:
./bitcoin-cli loadwallet mainYou need to load the wallet each time after starting elementsd.
Configuring the Hot Wallet in CAS
Create a Crypto Setting for L-BTC and specify the parameters for your node.
Hot Wallet Buy: select Liquid Network Bitcoin - Elements Core
Parameters: protocol : user : password : host : port : wallet
No spaces are permitted between the parameters (they’re used above only for clarification).
Example:
http:myuser:myPAZs2345x!2:123.321.123.321:7041:mainmyuseris the username that you specified in yourelements.confabove, andmyPAZs2345x!2is the password from the same file.The IP address
123.321.123.321is the public IP address of your node server on which the wallet tunnel (and elementsd) resides.7041is the standard port for elementsd node RPC.mainis the name of your wallet on the node.Make sure you load the wallet first as we mentioned above.
You need to load this wallet during every startup of elementsd.
Wallet Tunnel Password: this is automatically generated for you (and provided to you) during the GB Wallet Tunnel server installation as described here (if used).
Firewall Configuration
Configure the firewall after you’ve successfully connected and tested your CAS Crypto Setting.
This node needs to expose these ports:
22 (SSH),
22222 (GB Wallet Tunnel)
8332 (Bitcoin Core)
7042 (Liquid Network Elements Node)
Block off all other access/ports to reduce malicious actors' abuse/attacks on your node.
UFW, or Uncomplicated FireWall, is a simplified firewall management interface. UFW is included automatically with Ubuntu.
Check to see if UFW is already enabled and running:
sudo ufw statusIf UFW is enabled and working, it will report the active rules of allowed connections to your server - otherwise you'll see something like this:
Fresh/new systems will normally be inactive (the system is unprotected).
If it is not installed, install it now using:
sudo apt update && sudo apt install ufwIf UFW is active, then this procedure will erase that previous configuration and rewrite the rules.
Reset & deny all incoming connections by default:
sudo ufw resetThis will erase any/all previous UFW configuration.
Deny all public access to all ports:
sudo ufw default deny incomingNow we’re left to specify the exceptions (the “rules”).
Allow incoming TCP connections on ports 22, 22222, 8332, and 7042
sudo ufw allow 22/tcp
sudo ufw allow 22222/tcp
sudo ufw allow 8332/tcp
sudo ufw allow 7042/tcpFinally, enable & reload UFW to apply the new rules:
sudo ufw enable
sudo ufw reloadAssuming your commands succeeded, your node should now be protected by UFW.
Copyright © 2020-2026 General Bytes USA LLC