https://docs.stacks.co/start-mining/mainnet
The VM will not need a lot of resources to run a miner - the most resources will be consumed during blockchain sync.
A single CPU system with at least 4GB of memory should be more than sufficient - as well as roughly 1TB of total disk space
Note: btcuser
and btcpass
are used for bitcoin RPC auth in this doc. Change as appropriate
- Separate disks for chainstates and OS
- mount a dedicated disk for bitcoin at
/bitcoin
of 1TB - mount a dedicated disk for stacks-blockchain at
/stacks-blockchain
of at least 100GB - root volume
/
of at least 25GB
- mount a dedicated disk for bitcoin at
- Combined Disk for all data
- root volume
/
of at least 1TB
- root volume
$ sudo mkdir -p /bitcoin
$ sudo mkdir -p /stacks-blockchain
$ sudo mkdir -p /etc/bitcoin
$ sudo mkdir -p /etc/stacks-blockchain
$ curl -sL https://deb.nodesource.com/setup_16.x | sudo -E bash -
$ sudo apt-get update -y && sudo apt-get install -y build-essential jq netcat nodejs git autoconf libboost-system-dev libboost-filesystem-dev libboost-thread-dev libboost-chrono-dev libevent-dev libzmq5 libtool m4 automake pkg-config libtool libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-program-options-dev libboost-test-dev libboost-thread-dev libboost-iostreams-dev
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh && source $HOME/.cargo/env
mount the disks to each filesystem created above - edit /etc/fstab
to automount these disks at boot.
/dev/xvdb1 /bitcoin xfs rw,relatime,attr2,inode64,noquota
/dev/xvdc1 /stacks-blockchain xfs rw,relatime,attr2,inode64,noquota
Choose either method, but bitcoin is required here. Building from source ensures you know what code you are running, but will a while to compile.
$ sudo curl -L https://bitcoin.org/bin/bitcoin-core-22.0/bitcoin-22.0-x86_64-linux-gnu.tar.gz -o /tmp/bitcoin-22.0.tar.gz
$ sudo tar -xzvf /tmp/bitcoin-22.0.tar.gz -C /tmp
$ sudo cp /tmp/bitcoin-22.0/bin/* /usr/local/bin/
$ git clone --depth 1 --branch v22.0 https://github.com/bitcoin/bitcoin /tmp/bitcoin && cd /tmp/bitcoin
$ sh contrib/install_db4.sh .
$ ./autogen.sh
$ export BDB_PREFIX="/tmp/bitcoin/db4" && ./configure BDB_LIBS="-L${BDB_PREFIX}/lib -ldb_cxx-4.8" BDB_CFLAGS="-I${BDB_PREFIX}/include" \
--disable-gui-tests \
--enable-static \
--without-miniupnpc \
--with-pic \
--enable-cxx \
--with-boost-libdir=/usr/lib/x86_64-linux-gnu
$ make -j2
$ sudo make install
$ sudo bash -c 'cat <<EOF> /etc/bitcoin/bitcoin.conf
server=1
#disablewallet=1
datadir=/bitcoin
rpcuser=btcuser
rpcpassword=btcpass
rpcallowip=0.0.0.0/0
bind=0.0.0.0:8333
rpcbind=0.0.0.0:8332
dbcache=512
banscore=1
rpcthreads=256
rpcworkqueue=256
rpctimeout=100
txindex=1
EOF'
$ sudo useradd bitcoin
$ sudo chown -R bitcoin:bitcoin /bitcoin/
$ sudo bash -c 'cat <<EOF> /etc/systemd/system/bitcoin.service
[Unit]
Description=Bitcoin daemon
After=network.target
[Service]
ExecStart=/usr/local/bin/bitcoind -daemon \
-pid=/run/bitcoind/bitcoind.pid \
-conf=/etc/bitcoin/bitcoin.conf
# Process management
####################
Type=forking
PIDFile=/run/bitcoind/bitcoind.pid
Restart=on-failure
TimeoutStopSec=600
# Directory creation and permissions
####################################
# Run as bitcoin:bitcoin
User=bitcoin
Group=bitcoin
RuntimeDirectory=bitcoind
RuntimeDirectoryMode=0710
# Hardening measures
####################
# Provide a private /tmp and /var/tmp.
PrivateTmp=true
# Mount /usr, /boot/ and /etc read-only for the process.
ProtectSystem=full
# Deny access to /home, /root and /run/user
ProtectHome=true
# Disallow the process and all of its children to gain
# new privileges through execve().
NoNewPrivileges=true
# Use a new /dev namespace only populated with API pseudo devices
# such as /dev/null, /dev/zero and /dev/random.
PrivateDevices=true
[Install]
WantedBy=multi-user.target
EOF'
$ sudo systemctl daemon-reload
$ sudo systemctl enable bitcoin.service
$ sudo systemctl start bitcoin.service
now we wait a few days until bitcoin syncs to chain tip
$ sudo tail -f /bitcoin/debug.log
$ bitcoin-cli \
-rpcconnect=localhost \
-rpcport=8332 \
-rpcuser=btcuser \
-rpcpassword=btcpass \
getblockchaininfo | jq .blocks
save this output in a safe place!
$ cd $HOME && npm install @stacks/cli shx rimraf
$ npx @stacks/cli make_keychain 2>/dev/null | jq
{
"mnemonic": "frown lens very suit ocean trigger animal flip retire dose various mobile record emerge torch client sorry shy party session until planet member exclude",
"keyInfo": {
"privateKey": "ooxeemeitar4ahw0ca8anu4thae7aephahshae1pahtae5oocahthahho4ahn7eici",
"address": "STTXOG3AIHOHNAEH5AU6IEX9OOTOH8SEIWEI5IJ9",
"btcAddress": "Ook6goo1Jee5ZuPualeiqu9RiN8wooshoo",
"wif": "rohCie2ein2chaed9kaiyoo6zo1aeQu1yae4phooShov2oosh4ox",
"index": 0
}
}
We'll be using the wallet values from the previous npx
command, "btcAddress" and "wif"
$ bitcoin-cli \
-rpcconnect=localhost \
-rpcport=8332 \
-rpcuser=btcuser \
-rpcpassword=btcpass \
createwallet "miner"
$ sudo systemctl restart bitcoin
$ bitcoin-cli \
-rpcconnect=localhost \
-rpcport=8332 \
-rpcuser=btcuser \
-rpcpassword=btcpass \
importmulti '[{ "scriptPubKey": { "address": "<npx btcAddress>" }, "timestamp":"now", "keys": [ "<npx wif>" ]}]' '{"rescan": true}'
$ bitcoin-cli \
-rpcconnect=localhost \
-rpcport=8332 \
-rpcuser=btcuser \
-rpcpassword=btcpass \
getaddressinfo <npx btcAddress>
Once imported, the wallet will need to be funded with some bitcoin.
$ cd $HOME && cat <<EOF> $HOME/build-stacks.sh
#!/bin/sh
CURDIR=\$(pwd)
DEST=/usr/local/bin/stacks-node
GIT_DIR=\$HOME/stacks-blockchain
if [ ! -d \${GIT_DIR} ]; then
git clone https://github.com/blockstack/stacks-blockchain.git \${GIT_DIR}
else
git -C \${GIT_DIR} pull -r
fi
cd \${GIT_DIR}/testnet/stacks-node
cargo build --features monitoring_prom,slog_json --release --bin stacks-node
if [ "\$?" -eq "0" ]; then
if [ -f \${DEST} ]; then
sudo rm -f \${DEST}
fi
echo "Copying stacks-node to $DEST using sudo"
sudo cp -a \${GIT_DIR}/target/release/stacks-node \${DEST}
fi
cd \${CURDIR}
EOF
$ sh $HOME/build-stacks.sh
$ git clone https://github.com/blockstack/stacks-blockchain.git $HOME/stacks-blockchain
$ cd $HOME/stacks-blockchain/testnet/stacks-node
$ cargo build --features monitoring_prom,slog_json --release --bin stacks-node
$ sudo cp -a $HOME/stacks-blockchain/target/release/stacks-node /usr/local/bin/stacks-node
$ sudo bash -c 'cat <<EOF> /etc/stacks-blockchain/follower.toml
[node]
working_dir = "/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"
[burnchain]
chain = "bitcoin"
mode = "mainnet"
peer_host = "127.0.0.1"
username = "btcuser"
password = "btcpass"
rpc_port = 8332
peer_port = 8333
EOF'
replace seed
and local_peer_seed
with the privateKey
value from the previous npx
command
$ sudo bash -c 'cat <<EOF> /etc/stacks-blockchain/miner.toml
[node]
working_dir = "/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"
seed = "<npx privateKey>"
local_peer_seed = "<npx privateKey>"
miner = true
mine_microblocks = true
wait_time_for_microblocks = 10000
[burnchain]
chain = "bitcoin"
mode = "mainnet"
peer_host = "127.0.0.1"
username = "btcuser"
password = "btcpass"
rpc_port = 8332
peer_port = 8333
satoshis_per_byte = 100
#burn_fee_cap = 20000
burn_fee_cap = 450000
[miner]
first_attempt_time_ms = 5000
subsequent_attempt_time_ms = 180000
microblock_attempt_time_ms = 30000
[fee_estimation]
cost_estimator = "naive_pessimistic"
fee_estimator = "scalar_fee_rate"
cost_metric = "proportion_dot_product"
log_error = true
enabled = true
EOF'
$ sudo useradd stacks
$ sudo chown -R stacks:stacks /stacks-blockchain/
$ sudo bash -c 'cat <<EOF> /etc/systemd/system/stacks.service
[Unit]
Description=Stacks Blockchain
Requires=bitcoin.service
After=bitcoin.service
ConditionFileIsExecutable=/usr/local/bin/stacks-node
ConditionPathExists=/stacks-blockchain/
[Service]
ExecStart=/bin/sh -c "/usr/local/bin/stacks-node start --config=/etc/stacks-blockchain/follower.toml >> /stacks-blockchain/follower.log 2>&1"
ExecStartPost=/bin/sh -c "umask 022; sleep 2 && pgrep -f \"/usr/local/bin/stacks-node start --config=/etc/stacks-blockchain/follower.toml\" > /run/stacks-blockchain/stacks.pid"
ExecStopPost=/bin/sh -c "if [ -f \"/run/stacks-blockchain/stacks.pid\" ]; then rm -f /run/stacks-blockchain/stacks.pid; fi"
# Process management
####################
Type=simple
PIDFile=/run/stacks-blockchain/stacks.pid
Restart=on-failure
TimeoutStopSec=600
KillSignal=SIGTERM
# Directory creation and permissions
####################################
# Run as bitcoin:bitcoin
User=stacks
Group=stacks
RuntimeDirectory=stacks-blockchain
RuntimeDirectoryMode=0710
# Hardening measures
####################
# Provide a private /tmp and /var/tmp.
PrivateTmp=true
# Mount /usr, /boot/ and /etc read-only for the process.
ProtectSystem=full
# Deny access to /home, /root and /run/user
ProtectHome=true
# Disallow the process and all of its children to gain
# new privileges through execve().
NoNewPrivileges=true
# Use a new /dev namespace only populated with API pseudo devices
# such as /dev/null, /dev/zero and /dev/random.
PrivateDevices=true
[Install]
WantedBy=multi-user.target
EOF'
$ sudo systemctl daemon-reload
$ sudo systemctl enable stacks.service
$ sudo systemctl start stacks.service