How to launch a stacks-blockchain API instance
【Tips】 The reference document is running-api-from-source. Thanks to wileyj and whoabuddy for their contributions to the original document. This article is based on the above document to improve the database installation, background startup, Bitcoin node information and other details. *
In this document, we'll go over how to run a stacks-blockchain-api instance.
There are several components involved here to have a working setup, and we'll go over each.
Please note that the following guide is targetted for Debian based systems - that in mind, most of the commands will work on other Unix systems with some small adjustments.
- How to launch a stacks-blockchain API instance
Requirements
-
bash
or some other Unix-like shell (i.e.zsh
) -
sudo
or root level access to the system
PS: The following terminal interaction and output return are performed under Ubuntu 20.04 LTS
Initial Setup
Since we'll need to create some files/dirs for persistent data,
we'll first create a base directory structure and set some permissions:
$ sudo mkdir -p /stacks-node/{persistent-data/stacks-blockchain,bns,config,binaries}
$ sudo chown -R $(whoami) /stacks-node
$ cd /stacks-node
Install Requirements
Install Libs:
$ sudo apt-get install -y \
gnupg2 \
git \
lsb-release \
curl \
jq \
openjdk-11-jre-headless \
build-essential \
zip \
screen \
Install Postgres:
$ sudo apt install postgresql postgresql-contrib
# Success. You can now start the database server using:
# pg_ctlcluster 12 main start
$ sudo -i -u postgres
# postgres@iZj6c5ejo1w2ttwn79gprvZ:~$
$ exit
# logout
Install Nodejs
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.0/install.sh | bash
$ export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
$ nvm
# Node Version Manager (v0.37.0)
# Usage: ......
$ nvm install 14
# Now using node v14.18.1 (npm v6.14.15)
# Creating default alias: default -> 14 (-> v14.18.1)
$ node -v
# v14.18.1
$ npm -v
# 6.*.*
Optional but recommended - If you want the V1 BNS data, there are going to be a few extra steps:
**Download the BNS data: ** curl -L https://storage.googleapis.com/blockstack-v1-migration-data/export-data.tar.gz -o /stacks-node/bns/export-data.tar.g. z
**Extract the data: ** tar -xzvf ./bns/export-data.tar.gz -C /stacks-node/bns/
Each file in ./bns
will have a corresponding sha256
value.
To Verify, run a script like the following to check the sha256sum:
for file in `ls /stacks-node/bns/* | grep -v sha256 | grep -v .tar.gz`; do
if [ $(sha256sum $file | awk {'print $1'}) == $(cat ${file}.sha256 ) ]; then
echo "sha256 Matched $file"
else
echo "sha256 Mismatch $file"
fi
done
#sha256 Matched /stacks-node/bns/chainstate.txt
#sha256 Matched /stacks-node/bns/name_zonefiles.txt
#sha256 Matched /stacks-node/bns/subdomains.csv
#sha256 Matched /stacks-node/bns/subdomain_zonefiles.txt
Init Postgres
postgres permissions
We'll need to set a basic role, database to store data, and a password for the role.
Clearly, this password is insecure so modify password
to something stronger before creating the role.
$ cat <<EOF> /tmp/file.sql
create role stacks login password 'password';
create database stacks_db;
grant all on database stacks_db to stacks;
EOF
$ sudo su - postgres -c "psql -f /tmp/file.sql" && rm -f /tmp/file.sql
# CREATE ROLE
# CREATE DATABASE
# GRANT
$ echo "local all stacks md5" | sudo tee -a /etc/postgresql/12/main/pg_hba.conf
# local all stacks md5
$ sudo systemctl restart postgresql
stacks-blockchain-api
Create new screen:
$ screen
building stacks-blockchain-api
$ git clone https://github.com/blockstack/stacks-blockchain-api /stacks-node/stacks-blockchain-api && cd /stacks-node/stacks-blockchain-api \
&& echo "GIT_TAG=$(git tag --points-at HEAD)" >> .env \
&& npm config set unsafe-perm true \
&& npm install \
&& npm run build \
&& npm prune --production
starting stacks-blockchain-api
The stacks blockchain api requires several Environment Variables to be set in order to run properly.
To reduce complexity, we're going to create a .env
file that we'll use for these env vars.
** Note: ** to enable BNS names, uncomment BNS_IMPORT_DIR
in the below .env
file.
Create a new file: /stacks-node/stacks-blockchain-api/.env
with the following content:
$ cat <<EOF> /stacks-node/stacks-blockchain-api/.env
NODE_ENV=production
GIT_TAG=master
PG_HOST=localhost
PG_PORT=5432
PG_USER=stacks
PG_PASSWORD=password
PG_DATABASE=stacks_db
STACKS_CHAIN_ID=0x00000001
V2_POX_MIN_AMOUNT_USTX=90000000260
STACKS_CORE_EVENT_PORT=3700
STACKS_CORE_EVENT_HOST=0.0.0.0
STACKS_BLOCKCHAIN_API_PORT=3999
STACKS_BLOCKCHAIN_API_HOST=0.0.0.0
STACKS_BLOCKCHAIN_API_DB=pg
STACKS_CORE_RPC_HOST=localhost
STACKS_CORE_RPC_PORT=20443
#BNS_IMPORT_DIR=/stacks-node/bns
EOF
$ cd /stacks-node/stacks-blockchain-api && node ./lib/index.js
Exit screen:
# CTRL+A+D exit screen
stopping stacks-blockchain-api
No need to stop stacks-blockchain-api unless there are special circumstances.
$ ps -ef | grep "lib/index.js" | grep -v grep
user 17788 827 39 18:14 pts/0 00:07:55 node ./lib/index.js
$ sudo kill $(ps -ef | grep "lib/index.js" | grep -v grep | awk {'print $2'})
stacks-blockchain
Create new screen:
$ screen
In order to have a usable API instance, it needs to have data from a running stacks-blockchain instance.
You will need to have the following in your Config.toml
- this config block will send blockchain events to the API instance that was previously started:
[[events_observer]]
endpoint = "<fqdn>:3700"
retry_count = 255
events_keys = ["*"]
Here is an example Config.toml
that you can use - create this file as /stacks-node/config/Config.toml
:
$ cat <<EOF> /stacks-node/config/Config.toml
[node]
working_dir = "/stacks-node/persistent-data/stacks-blockchain"
rpc_bind = "0.0.0.0:20443"
p2p_bind = "0.0.0.0:20444"
bootstrap_node = "02da7a464ac770ae8337a343670778b93410f2f3fef6bea98dd1c3e9224459d36b@seed-0.mainnet.stacks.co:20444,02afeae522aab5f8c99a00ddf75fbcb4a641e052dd48836408d9cf437344b63516@seed-1.mainnet.stacks.co:20444,03652212ea76be0ed4cd83a25c06e57819993029a7b9999f7d63c36340b34a4e62@seed-2.mainnet.stacks.co:20444"
wait_time_for_microblocks = 10000
[[events_observer]]
endpoint = "localhost:3700"
retry_count = 255
events_keys = ["*"]
[burnchain]
chain = "bitcoin"
mode = "mainnet"
peer_host = "<ENTER-YOUR-OWN-BITCOIN-NODE-IP>"
username = "<ENTER-YOUR-OWN-BITCOIN-NODE-RPC-USERNAME>"
password = "<ENTER-YOUR-OWN-BITCOIN-NODE-RPC-PASSWORD>"
rpc_port = 8332
peer_port = 8333
EOF
stacks-blockchain binaries
Download latest release binary from https://github.com/blockstack/stacks-blockchain/releases/latest
**Linux archive for latest release: **
$ curl -L https://github.com/blockstack/stacks-blockchain/releases/download/$(curl --silent https://api.github.com/repos/blockstack/stacks-blockchain/releases/latest | jq .name -r | cut -f2 -d " ")/linux-x64.zip -o /tmp/linux-x64.zip
Extract the zip archive:
$ unzip /tmp/linux-x64.zip -d /stacks-node/binaries
starting stacks-blockchain
$ cd /stacks-node && nohup /stacks-node/binaries/stacks-node start --config /stacks-node/config/Config.toml &
stopping stacks-blockchain
No need to stop stacks-blockchain unless there are special circumstances.
$ ps -ef | grep "/stacks-node/binaries/stacks-node" | grep -v grep
user 17835 17834 99 18:17 pts/0 00:20:23 /stacks-node/binaries/stacks-node start --config /stacks-node/config/Config.toml
$ sudo kill $(ps -ef | grep "/stacks-node/binaries/stacks-node" | grep -v grep | awk {'print $2'})
Verify Everything is running correctly
Postgres
To verfiy the database is ready:
- Connect to the DB instance:
psql -h localhost -U stacks stacks_db
- use the password from the Postgres Permissions Step
- List current databases:
\l
- Disconnect from the DB :
\q
stacks-blockchain testing
$ curl localhost:20443/v2/info | jq
{
"peer_version": 402653184,
"pox_consensus": "e99b880a26405d3cda724f4c2b815ca0e7b681a8",
"burn_block_height": 666201,
"stable_pox_consensus": "8be2fc9f9156b31af688b9e3c484dc7a26cefc4f",
"stable_burn_block_height": 666194,
"server_version": "stacks-node 2.0.11.0.0 (master:bf4a577+, release build, linux [x86_64])",
"network_id": 1,
"parent_network_id": 3652501241,
"stacks_tip_height": 92,
"stacks_tip": "a251bfa158c7887c575798b79c8df57190690e023af245e45513110399c0cb5f",
"stacks_tip_consensus_hash": "ae29e81af9e7febfd4af6b53a3e515660a84150c",
"genesis_chainstate_hash": "74237aa39aa50a83de11a4f53e9d3bb7d43461d1de9873f402e5453ae60bc59b",
"unanchored_tip": "9fb08dd696d4e05bd042998dba8dd204ee64e11266cd4fba95b3a7bdaa709400",
"unanchored_seq": 0,
"exit_at_block_height": null
}
stacks-blockchain-api testing
$ curl localhost:3999/v2/info | jq
{
"peer_version": 402653184,
"pox_consensus": "e99b880a26405d3cda724f4c2b815ca0e7b681a8",
"burn_block_height": 666201,
"stable_pox_consensus": "8be2fc9f9156b31af688b9e3c484dc7a26cefc4f",
"stable_burn_block_height": 666194,
"server_version": "stacks-node 2.0.11.0.0 (master:bf4a577+, release build, linux [x86_64])",
"network_id": 1,
"parent_network_id": 3652501241,
"stacks_tip_height": 93,
"stacks_tip": "74223951b9dddfe82b1b116c852f0a14ff9432270d680042a5ef11cb0533b935",
"stacks_tip_consensus_hash": "2d521daf879f2e00f745c47000b856e1d41b15d4",
"genesis_chainstate_hash": "74237aa39aa50a83de11a4f53e9d3bb7d43461d1de9873f402e5453ae60bc59b",
"unanchored_tip": "9fb08dd696d4e05bd042998dba8dd204ee64e11266cd4fba95b3a7bdaa709400",
"unanchored_seq": 0,
"exit_at_block_height": null
}
stacks-node folder tree
root@/stacks-node $ pwd
# /stacks-node
root@/stacks-node $ tree -L 1
.
├── binaries
├── bns
├── config
├── persistent-data
└── stacks-blockchain-api