Terraforming Bitcoin Testnets — Part 2/3
At bloXroute Labs, we are developing a Block Distribution Network (BDN, akin to Akamai for blockchains) in order to reduce propagation times and therefore reduce orphan and uncle block (for ETH) rates in any blockchain network, allowing for throughput increases.
In Part 1, we covered building a basic network of a full node and miner. In today’s Part 2, we will discuss how we created our Bitcoin Docker images, and simple scripts for managing and interacting with networks. In Part 3, we’ll cover how Bitcoin peering works and how we automated the specification of peering topologies.
Since the point of bloXroute is to enable blockchains to shuttle data faster than would normally be safe (avoiding chain splits), we needed to hack Bitcoin to be faster, so that we could “break the network” by transmitting larger blocks faster. Bitcoin Core produces small blocks only once every 10 mins, so it never had optimized the mempool to handle a level of throughput beyond this.
Dockerizing your Bitcoin Build
We picked the Bitcoin Unlimited client as a starting point because they had already done work to make the mempool more scalable. We also made our own changes to the protocol, patching the PoW algorithm so that we could mine blocks on demand while still using “real” PoW. To Dockerize this project, we forked it on github, and added a Dockerfile:
We supplied our own bitcoin.conf, but it was close to default settings.
Pushing the Docker build to ECR
Once the image was built, we built and pushed it to Amazon’s Elastic Container Registry.
docker build . -t ourbitcoin
docker tag -t ourbitcoin $AWS_ACCOUNT.dkr.ecr.us-east-1.amazonaws.com/bloxroute-bitcoin:latest
$(aws ecr get-login --no-include-email)
docker push $AWS_ACCOUNT.dkr.ecr.us-east-1.amazonaws.com/bloxroute-bitcoin:latest
Now on boot, we run the bitcoin image in our boot script, covered in Part 1. In our boot script, we take the rpcuser and rpcpassword, which are injected into our AWS instance tags via terraform, and we put them into /etc/environment like this, so that we can use them to interact with the node later:
echo "export rpcpassword=$TAG_rpcpassword" >> /etc/environment
echo "export rpcuser=$TAG_rpcuser" >> /etc/environment
Interacting with a single Bitcoin node
Once the image is up and running, we provide a convenience script called
/usr/local/bin/btcrpc which will allow developers to issue rpc commands easily using those env vars.
Now, developers on the node can easily talk to bitcoin:
# See if it's mining
# Get info about peers
# Add a node
btcrpc addnode 126.96.36.199 add
# Send a transaction - this is us sending 0.1btc to ourselves on a new address
btcrpc sendtoaddress $(btcrpc getnewaddress) 0.1
This makes interacting with the node much easier. But we can go further!
Managing Fleets of Bitcoin Nodes
Let’s make some commands that let us inspect and interact with bitcoin on all our nodes. These assume an OSX environment with
brew install pssh available. Here are two scripts:
run-cmd which allow us to list all the nodes in a particular bitcoin network and run a command in parallel:
With these two scripts, we can now see the mining status of all our bitcoin nodes:
run-cmd.sh mynetworkname btcrpc getmininginfo
This makes it easy to inspect chain state across the network and see if any nodes have fallen behind as we stress test them.
During our stress tests, we pump lots of transactions through the Bitcoin network. Because of this, we found it was good to have an initial chain state where we had mined a bunch of blocks to use as our fund pool. To do this, we ran a normal Bitcoin node, let it mine for a bit, then saved the chain state using our
Once we had this backup, we then created a btcrestore script on all our nodes:
Once we had this script, we could then tell the entire network to restore to a particular chainstate using
This script was very useful in bringing back known good chain states to make sure our stress tests had a common starting point.
That’s all for today! In Part 3, we will cover Bitcoin peering and custom peering topologies.