BTC-Staker is a toolset designed for seamless Bitcoin staking. It consists of two components:
stakerd
- The stakerd
daemon manages connections to the Babylon and Bitcoin
nodes.
stakercli
- The stakercli
is a command line interface (CLI) to facilitate
interaction with the stakerd
daemon . It enables users to stake funds, withdraw
funds, unbond staked funds, retrieve the active finality providers set in Babylon,
and more. It serves as an intuitive interface for effortless control and
monitoring of your Bitcoin staking activities.
The stakerd
daemon requires a running Bitcoin node and a legacy wallet loaded
with signet Bitcoins to perform staking operations.
You can configure stakerd
daemon to connect to either
bitcoind
or btcd
node types. While both are compatible, we recommend
using bitcoind
. Ensure that you are using legacy wallets, as stakerd
daemon
doesn't currently support descriptor wallets.
Below, we'll guide you through setting up a signet bitcoind
node and a legacy
wallet:
# Download Bitcoin Core binary
wget https://bitcoincore.org/bin/bitcoin-core-26.0/bitcoin-26.0-x86_64-linux-gnu.tar.gz
# Extract the downloaded archive
tar -xvf bitcoin-26.0-x86_64-linux-gnu.tar.gz
# Provide execution permissions to binaries
chmod +x bitcoin-26.0/bin/bitcoind
chmod +x bitcoin-26.0/bin/bitcoin-cli
Please update the following configurations in the provided file:
<your_rpc_username>
and <your_rpc_password>
with your own values.
These credentials will also be utilized in the btc-staker configuration file later
on.<user>
is set to the machine user. In the guide below, it's set
to ubuntu
.deprecatedrpc=create_bdb
is necessary to enable the creation of a
legacy wallet, which has been deprecated in the latest core version. For more
information, refer to the Bitcoin Core 26.0 release
page here
and this link.rpcallowip=0.0.0.0/0
and rpcbind=0.0.0.0
to the bitcoind command.bitcoind
with -txindex
option to make sure btc-staker can get
all needed bitcoin transaction data.# Create the service file
sudo tee /etc/systemd/system/bitcoind.service >/dev/null <<EOF
[Unit]
Description=bitcoin signet node
After=network.target
[Service]
User=<user>
Type=simple
ExecStart=/home/ubuntu/bitcoin-26.0/bin/bitcoind \
-deprecatedrpc=create_bdb \
-signet \
-server \
-txindex \
-rpcport=38332 \
-rpcuser=<your_rpc_username> \
-rpcpassword=<your_rpc_password>
Restart=on-failure
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
EOF
# Start the service
sudo systemctl daemon-reload
sudo systemctl enable bitcoind
sudo systemctl start bitcoind
# Check the status and logs of the service
systemctl status bitcoind
journalctl -u bitcoind -f
~/bitcoin-26.0/bin/bitcoin-cli -signet \
-rpcuser=<your_rpc_username> \
-rpcpassword=<your_rpc_password> \
-rpcport=38332 \
-named createwallet \
wallet_name=btcstaker \
passphrase="<passphrase>" \
load_on_startup=true \
descriptors=false
rpcuser
, rpcpassword
, rpcport
that you used while
setting up the bitcoind systemd service.-named createwallet
indicates that a new wallet should be created with the
provided name.wallet_name=btcstaker
specifies the name of the new wallet and <passphrase>
corresponds to the wallet pass phrase. Ensure you use the wallet name and
passphrase configured here in the walletconfig
section of the stakerd.conf
file.load_on_startup=true
ensures that the wallet automatically loads during
system startup.descriptors=false
disables descriptors, which are not currently supported by the
btc-staker.You can load the wallet with the loadwallet
command:
~/bitcoin-26.0/bin/bitcoin-cli -signet \
-rpcuser=<your_rpc_username> \
-rpcpassword=<your_rpc_password> \
-rpcport=38332 \
loadwallet "btcstaker"
where rpcuser
, rpcpassword
, and rpcport
correspond to the RPC configuration you
have set up and "btcstaker"
should be replaced with the wallet name that you
created.
You can generate a btc address through the getnewaddress
command:
~/bitcoin-26.0/bin/bitcoin-cli -signet \
-rpcuser=<your_rpc_username> \
-rpcpassword=<your_rpc_password> \
-rpcport=38332 \
getnewaddress
where rpcuser
, rpcpassword
, and rpcport
correspond to the RPC configuration you
have set up.
Use the faucet link to request signet BTC to the address generated in the previous step. You can use the following commands if you have received the funds
You can immediately see the amount using getunconfirmedbalance
~/bitcoin-26.0/bin/bitcoin-cli -signet \
-rpcuser=<your_rpc_username> \
-rpcpassword=<your_rpc_password> \
-rpcport=38332 \
getunconfirmedbalance
You can also see info about the transaction that the faucet gave you
using gettransaction
~/bitcoin-26.0/bin/bitcoin-cli -signet \
-rpcuser=<your_rpc_username> \
-rpcpassword=<your_rpc_password> \
-rpcport=38332 \
gettransaction $TXID
where $TXID
is the transaction id that you received from the faucet.
Once the tx is confirmed you can check the funds using getbalance
command
~/bitcoin-26.0/bin/bitcoin-cli -signet \
-rpcuser=<your_rpc_username> \
-rpcpassword=<your_rpc_password> \
-rpcport=38332 \
getbalance
Notes:
journalctl -u bitcoind -f
. It should show you the progress percentage for
example it is progress=0.936446
in this log
Jan 29 18:55:50 ip-172-31-85-49 bitcoind[71096]:
2024-01-29T18:55:50Z UpdateTip: new best=00000123354567a29574e6bdd263409b8eab6c05c6ef2abad959b092bf61fe9a
height=169100 version=0x20000000 log2_work=40.925924 tx=2319364
date='2023-11-12T19:42:53Z' progress=0.936446
cache=255.6MiB(1455996txo)
Alternatively, you can also check the latest block in a btc explorer like https://mempool.space/signet and compare it with the latest block in your node.
~/bitcoin-26.0/bin/bitcoin-cli -signet \
-rpcuser=<your_rpc_username> \
-rpcpassword=<your_rpc_password> \
-rpcport=38332 \
getwalletinfo
The output should be similar to this and the format
should be bdb
:
{
"walletname": "btcstaker",
"walletversion": 169900,
"format": "bdb",
"balance": 0.00000000,
"unconfirmed_balance": 0.00000000,
"immature_balance": 0.00000000,
"txcount": 0,
"keypoololdest": 1706554908,
"keypoolsize": 1000,
"hdseedid": "9660319ab465abc05db95ad17cb59a9ec8f106fd",
"keypoolsize_hd_internal": 1000,
"unlocked_until": 0,
"paytxfee": 0.00000000,
"private_keys_enabled": true,
"avoid_reuse": false,
"scanning": false,
"descriptors": false,
"external_signer": false
}
bitcoin.conf
instead of using flags in the bitcoind
cmd.
Please check the Bitcoin signet wiki and this
manual here to learn how to
set bitcoin.conf
. Ensure you have configured the bitcoind.conf
correctly and
set all the required parameters as shown in the systemd service file above.This project requires Go version 1.21 or later.
Install Go by following the instructions on the official Go installation guide.
Install essential tools and packages needed to compile and build the binaries.
sudo apt install build-essential
To get started, clone the repository to your local machine from Github:
git clone https://github.com/babylonchain/btc-staker.git
You can choose a specific version from the official releases page
cd btc-staker # cd into the project directory
git checkout <release-tag>
At the top-level directory of the project
make install
The above command will build and install the following binaries to
$GOPATH/bin
:
stakerd
: The daemon program for the btc-stakerstakercli
: The CLI tool for interacting with the stakerd.If your shell cannot find the installed binaries, make sure $GOPATH/bin
is in
the $PATH
of your shell. Usually these commands will do the job
export PATH=$HOME/go/bin:$PATH
echo 'export PATH=$HOME/go/bin:$PATH' >> ~/.profile
The stakerd
daemon requires a keyring with loaded Babylon tokens to pay for the
transactions. Follow this
guide
to create a keyring and request funds.
stakerd
) configurationstakercli
tool serves as a control plane for the Staker Daemon.
Initialize the home directory for the Staker Daemon and dump the default configuration file to the specified directory.
stakercli admin dump-config --config-file-dir /path/to/stakerd-home/
After initialization, the home directory will have the following structure
ls /path/to/stakerd-home/
├── stakerd.conf
If the --config-file-dir
flag is not specified, then the default home directory
will be used. For different operating systems, those are:
~/Library/Application Support/Stakerd
~/.Stakerd
C:\Users\<username>\AppData\Local\Stakerd
In the following, we go through important parameters of the stakerd.conf
file.
Notes:
Key
parameter in the config below is the name of the key in the keyring to
use for signing transactions. Use the key name you created
in Create a Babylon keyring with fundsKeyDirectory
is set to the location where the keyring is
stored.test
keyring backendChainID
for the network you're connecting to. For
example, for Babylon devnet, the chain ID is bbn-dev-5
.To change the Babylon RPC/GRPC address, update the following:
RPCAddr = https://rpc.devnet.babylonchain.io:443 # rpc node address
GRPCAddr = https://grpc.devnet.babylonchain.io:443 # grpc node address
The above addresses are for Babylon devnet.
If you encounter any gas-related errors while performing staking operations,
consider adjusting the GasAdjustment
and GasPrices
parameters. For example,
you can set:
GasAdjustment = 1.5
GasPrices = 0.002ubbn
[babylon]
# Name of the key in the keyring to use for signing transactions
Key = btc-staker
# Chain id of the chain (Babylon)
ChainID = bbn-test
# Address of the chain's RPC server (Babylon)
RPCAddr = http://localhost:26657
# Address of the chain's GRPC server (Babylon)
GRPCAddr = https://localhost:9090
# Directory to store staker keys in
KeyDirectory = /path/to/stakerd-home/
Notes:
[chain]
# btc network to run on
Network = signet
[btcnodebackend]
# type of node to connect to {bitcoind, btcd}
Nodetype = bitcoind
# type of wallet to connect to {bitcoind, btcwallet}
WalletType = bitcoind
# fee mode to use for fee estimation {static, dynamic}. In dynamic mode fee will be estimated using backend node
FeeMode = static
Note: Make sure you create a BTC wallet, name it appropriately, and load it with enough signet BTC.
[walletconfig]
# name of the wallet to sign Bitcoin transactions.
# this should be the same as set in createwallet command in bitcoind.
WalletName = btcstaker
# passphrase to unlock the wallet
WalletPass = walletpass
[walletrpcconfig]
# location of the wallet rpc server
# note: in case of bitcoind, the wallet host is same as the rpc host
Host = localhost:38332
# user auth for the wallet rpc server
# note: in case of bitcoind, the wallet rpc credentials are same as rpc credentials
# this should be the same as set in the bitcoind daemon
User = your_rpc_username
# password auth for the wallet rpc server. This should be the same as set in the bitcoind daemon
Pass = your_rpc_password
# disables tls for the wallet rpc client
DisableTls = true
Make sure to replace the following important parameters related to bitcoind
as per
your setup.
[bitcoind]
# The daemon's rpc listening address
# note: P2P port for signet is 38332/38333
# mainnet 8332/8333
# testnet 18332/18333
# regtest 18443
# ref - https://github.com/bitcoin/bitcoin/blob/03752444cd54df05a731557968d5a9f33a55c55c/src/chainparamsbase.cpp#L39
RPCHost = 127.0.0.1:38332
# Username for RPC connections. This should be the same as set in the bitcoind daemon
RPCUser = your_rpc_username
# Password for RPC connections. This should be the same as set in the bitcoind daemon
RPCPass = your_rpc_password
# The address listening for ZMQ connections to deliver raw block notifications
ZMQPubRawBlock = tcp://127.0.0.1:29001
# The address listening for ZMQ connections to deliver raw transaction notifications
ZMQPubRawTx = tcp://127.0.0.1:29002
To see the complete list of configuration options, check the stakerd.conf
file.
You can start the staker daemon using the following command:
stakerd
This will start the Staker daemon RPC server at the address specified in the configuration under
the RawRPCListeners
field. A custom address can also be specified using
the --rpclisten
flag.
stakerd --rpclisten 'localhost:15812'
time="2023-12-08T11:48:04+05:30" level=info msg="Starting StakerApp"
All the available CLI options can be viewed using the --help
flag. These options
can also be set in the configuration file.
The following guide will show how to stake, withdraw, and unbond Bitcoin.
Find the BTC public key of the finality provider you intend to stake to.
When staking, specify the BTC public key of a single finality provider using the
--finality-providers-pks
flag in the stake
command.
Note Make sure to use only one finality provider BTC public key in
the --finality-providers-pks
flag of the
stake
command, as multiple providers are not currently supported.
stakercli daemon babylon-finality-providers
{
"finality_providers": [
{
"babylon_public_Key": "0294092d0266c8d26544291b692e13f1e4fcba7829c5445ff99fcb3aefb23fe7cd",
"bitcoin_public_Key": "3328782c63404386d9cd905dba5a35975cba629e48192cea4a348937e865d312"
}
],
"total_finality_providers_count": "1"
}
Find the BTC address that has sufficient Bitcoin balance that you want to stake from.
Note: In case you don't have addresses with adequate balances, you can use the faucet to receive signet BTC. Visit the faucet link to acquire signet BTC.
stakercli daemon list-outputs
{
"outputs": [
{
"amount": "10 BTC",
"address": "bcrt1q56ehztys752uzg7fzpear08l5mw8w2kxgz7644"
},
{
"amount": "10 BTC",
"address": "bcrt1ql94x9v78ag7qx896f0axka809u55pla8cywsvn"
}
]
}
Stake Bitcoin to the finality provider of your choice. The --staking-time
flag
specifies the timelock of the staking transaction in BTC blocks.
The --staking-amount
flag specifies the amount in satoshis to stake.
stakercli daemon stake \
--staker-address bcrt1q56ehztys752uzg7fzpear08l5mw8w2kxgz7644 \
--staking-amount 1000000 \
--finality-providers-pks 3328782c63404386d9cd905dba5a35975cba629e48192cea4a348937e865d312 \
--staking-time 10000 # ~70 days
# Transaction details
{
"tx_hash": "6bf442a2e864172cba73f642ced10c178f6b19097abde41608035fb26a601b10"
}
Note: You can self delegate i.e. stake to your own finality provider. Follow
the finality provider registration guide
to create and register a finality provider to Babylon. Once the finality provider is
registered, you can use your finality provider BTC public key in
the --finality-providers-pks
flag of the stake
command.
The unbond
cmd initiates the unbonding flow which involves communication with the
Babylon chain, Covenant emulators, and the BTC chain. It
--staking-transaction-hash
is the transaction hash from the response of the stake
command.
stakercli daemon unbond \
--staking-transaction-hash 6bf442a2e864172cba73f642ced10c178f6b19097abde41608035fb26a601b10
Note:
stakercli daemon list-staking-transactions
The staker can withdraw the staked funds after the timelock of the staking or unbonding transaction expires.
--staking-transaction-hash
is the transaction hash from the response of stake
command.
stakercli daemon unstake \
--staking-transaction-hash 6bf442a2e864172cba73f642ced10c178f6b19097abde41608035fb26a601b10
Note: You can also use this cmd to get the list of all withdrawable staking transactions in db.
stakercli daemon withdrawable-transactions
In order to unstake
you'll need to wait for your staking/unbonding tx to be deep
enough in btc so that the timelock expires.