Running a Testnet with Bitcoin on Linux
Tags: blockchain, linux, tutorial, bitcoin
Published: 2021-09-13 07:14:02

This will be a series of posts on:
- The basics of Blockchain (this post)
- Setting up a Bitcoin Full-Node on Linux (this post)
- CLI and JSON RPC examples to interact with the blockchain and your wallet ([post 2](https://dev.to/ruanbekker/interacting-with-your-bitcoin-node-113c))

In this in-depth tutorial, we will cover the **basics of blockchain**, why you would want a **bitcoin full-node**, how to setup a bitcoin full-node on linux using the **testnet chain** and how to interact with your **node and the blockchain** using the cli and the json rpc, where we will create wallets and addresses and sending tbtc to your accounts.

## Blockchain Basics

Before we start setting up our bitcoin full-node, we first need to get through some blockchain basics, if you already aware of it, you can skip the the setup section of this post.

### Block

Transaction data is **permanently recorded** into files called **blocks**. You can think of it as a **transaction ledger**. Blocks are organised into a linear sequence over time.

New transactions are **constantly being processed** by **miners** into new blocks which are added to the **end of the chain**. As blocks are buried deeper and deeper into the blockchain they **become harder** and harder to change or remove, this gives rise of **[Bitcoin's Irreversible Transactions](https://en.bitcoin.it/wiki/Irreversible_Transactions)**.

The first block added to the blockchain is referred to as the **[genesis block](https://en.bitcoin.it/wiki/Genesis_block)**

### Blockchain

A blockchain is a transaction database shared by **all nodes participating** in a system based on the bitcoin protocol. A **full copy** of a currency's blockchain contains **every** transaction ever executed in the currency. With this information, one can find out how much value belonged to each address at any point in history.

Every block contains a hash of the previous block. This has the effect of creating a chain of blocks from the genesis block to the current block. **Each block** is guaranteed to come after the **previous block** chronologically because the previous block's hash would otherwise not be known. Each block is also computationally impractical to modify once it has been in the chain for a while because every block after it would also have to be regenerated. **These properties are what make bitcoins transactions irreversible**. The blockchain is the main innovation of Bitcoin.

### Mining

Mining is the **process** of **adding transaction records** to bitcoin's public ledger of past transactions. The term "mining rig" is referred to where as a single computer system that performs the necessary computations for "mining".

The blockchain serves to confirm transactions to the rest of the network as having taken place. Bitcoin nodes use the blockchain to **distinguish legitimate Bitcoin transactions** from attempts to re-spend coins that have already been spent elsewhere.

### Node

Any **computer** that connects to the **bitcoin network** is called a **node**. Nodes that fully verify all of the rules of bitcoin are called full nodes. The most popular software implementation of full nodes is called bitcoin-core, its releases can be found on their **[github page](https://github.com/bitcoin/bitcoin/releases)**

### What is a Full Node

A full node is a node (computer system with bitcoin-core running on it) which **downloads every block and transaction** and check them against **bitcoin's consensus rules**. which fully validates transactions and blocks. Almost all full nodes also help the network by accepting transactions and blocks from other full nodes, validating those transactions and blocks, and then relaying them to further full nodes.

Some **examples** of **consensus rules**:

* Blocks may only [create](https://en.bitcoin.it/wiki/Controlled_supply) a certain number of bitcoins. (Currently 6.25 BTC per block.)
* Transactions must have correct signatures for the bitcoins being spent.
* Transactions/blocks must be in the correct data format.
* Within a single [blockchain](https://en.bitcoin.it/wiki/Block_chain), a transaction output cannot be double-spent.

At minimum, a full node must download every transaction that has ever taken place, all new transactions, and all block headers. Additionally, full nodes must store information about every unspent transaction output until it is spent.

By default full nodes are inefficient in that they download each new transaction at least twice, and they store the entire block chain (more than 165 GB as of 20180214) forever, even though only the unspent transaction outputs (<2 GB) are required. Performance can improved by enabling [-blocksonly](https://bitcointalk.org/index.php?topic=1377345.0) mode and enabling [pruning](https://bitcoin.org/en/release/v0.12.0#wallet-pruning)

### Archival Nodes

A subset of full nodes also **accept incoming connections** and **upload old blocks** to other peers on the network. This happens if the software is run with -listen=1 as is default.

Contrary to some popular misconceptions, being an archival node is not necessary to being a full node. If a user's bandwidth is constrained then they can use -listen=0, if their disk space is constrained they can use pruning, all the while still being a fully-validating node that enforces bitcoin's consensus rules and contributing to bitcoin's overall security.

Most information was referenced from **[this](https://en.bitcoin.it/wiki/Full_node)** wiki.

## Setup Bitcoin Core

Now for the fun part, to setup bitcoin-core on linux, in my case I am using a fresh **Ubuntu 20.04** instance and the following commands will be executed as a non-root user.

### Environment Variables

Set the following environment variables, the latest version for `BITCOIN_VERSION` can be retrieved at: https://bitcoincore.org/bin/, execute the following:

```bash
$ export ARCH=x86_64
$ export BITCOIN_VERSION=0.21.1
$ export BITCOIN_URL=https://bitcoincore.org/bin/bitcoin-core-${BITCOIN_VERSION}/bitcoin-${BITCOIN_VERSION}-${ARCH}-linux-gnu.tar.gz
$ export BITCOIN_DATA_DIR=/blockchain/bitcoin/data
```

### Installation

Create the user and group for bitcoin:

```bash
$ sudo groupadd -r bitcoin
$ sudo useradd -r -m -g bitcoin -s /bin/bash bitcoin
```

Update the package manager and install the dependencies:

```bash
$ sudo apt update && sudo apt install ca-certificates gnupg gpg wget jq --no-install-recommends -y
```

Download bitcoin-core and verify that the package matches the sha hash:

```bash
$ cd /tmp
$ wget https://bitcoincore.org/bin/bitcoin-core-${BITCOIN_VERSION}/SHA256SUMS.asc
$ wget -qO bitcoin-${BITCOIN_VERSION}-${ARCH}-linux-gnu.tar.gz "${BITCOIN_URL}"
$ cat SHA256SUMS.asc | grep bitcoin-${BITCOIN_VERSION}-${ARCH}-linux-gnu.tar.gz | awk '{ print $1 }'
```

Extract the package to `/opt/bitcoin/${BITCOIN_VERSION}` and exclude any graphical user interfacing binaries, create the home directory and set the ownership:

```bash
$ sudo mkdir -p /opt/bitcoin/${BITCOIN_VERSION}
$ sudo mkdir -p ${BITCOIN_DATA_DIR}
$ sudo tar -xzvf bitcoin-${BITCOIN_VERSION}-${ARCH}-linux-gnu.tar.gz -C /opt/bitcoin/${BITCOIN_VERSION} --strip-components=1 --exclude=*-qt
$ sudo ln -s /opt/bitcoin/${BITCOIN_VERSION} /opt/bitcoin/current
$ sudo rm -rf /tmp/*
$ sudo chown -R bitcoin:bitcoin ${BITCOIN_DATA_DIR}
```

When you have to upgrade the software version of bitcoin-core in the future you can remove the symlink with `sudo rm -rf /usr/local/bitcoin/current` and symlink to the newer version as shown above.

### Configuration

Create the bitcoin configuration, here you see I am using the testnet chain and due to storage restrictions for my use-case I am setting `pruning` mode to 1GB, and if you don't set `BITCOIN_RPC_USER` it will use the user `bitcoin` and if you don't set `BITCOIN_RPC_PASSWORD` it will generate a password for the json-rpc interface: 

```bash
$ cat > bitcoin.conf.tmp << EOF
datadir=${BITCOIN_DATA_DIR}
printtoconsole=1
rpcallowip=127.0.0.1
rpcuser=${BITCOIN_RPC_USER:-bitcoin}
rpcpassword=${BITCOIN_RPC_PASSWORD:-$(openssl rand -hex 24)}
testnet=1
prune=1000
[test]
rpcbind=127.0.0.1
rpcport=18332
EOF
```

Create the systemd unit-file for bitcoind:

```bash
$ cat > bitcoind.service <<  EOF
[Unit]
Description=Bitcoin Core Testnet
After=network.target

[Service]
User=bitcoin
Group=bitcoin
WorkingDirectory=${BITCOIN_DATA_DIR}

Type=simple
ExecStart=/usr/local/bitcoin/current/bin/bitcoind -conf=$BITCOIN_DATA_DIR/bitcoin.conf

[Install]
WantedBy=multi-user.target
EOF
```

Now move the temporary config files, change the ownership and symlink the bitcoin home directory to the path that we created earlier:

```bash
$ sudo mv bitcoin.conf.tmp $BITCOIN_DATA_DIR/bitcoin.conf
$ sudo chown bitcoin:bitcoin $BITCOIN_DATA_DIR/bitcoin.conf
$ sudo chown -R bitcoin $BITCOIN_DATA_DIR
$ sudo ln -sfn $BITCOIN_DATA_DIR /home/bitcoin/.bitcoin
$ sudo chown -h bitcoin:bitcoin /home/bitcoin
$ sudo chown -R bitcoin:bitcoin /home/bitcoin
```

Move the systemd unit file in place, then reload systemd and start bitcoind:

```bash
$ sudo mv bitcoind.service /etc/systemd/system/bitcoind.service
$ sudo systemctl daemon-reload
$ sudo systemctl enable bitcoind
$ sudo systemctl start bitcoind
```

Switch to the `bitcoin` user:

```bash
$ sudo su - bitcoin
```

And append the bitcoin path to the `~/.profile` file so that your user know where to find the bitcoin binaries:

```bash
$ export PATH=$PATH:/opt/bitcoin/current/bin
```

## Initial Block Download

Once bitcoind process has started, the initial block download will start and you can get the progress as the bitcoin user using the cli:

```bash
$ bitcoin-cli -getinfo
```

Or as the root user you can view the progress using `journalctl`:

```bash
$ sudo journalctl -fu bitcoind
Sep 03 08:44:23 rpi-01 bitcoind[532]: 2021-09-03T06:44:23Z UpdateTip: new best=x height=2091205 version=0x20c00000 log2_work=74.461678 tx=60938712 date='2021-09-03T06:44:13Z' progress=1.000000 cache=1.7MiB(13673txo)
```

### Troubleshooting

If you run into any issues you can see the status of bitcoind using:

```bash
$ sudo systemctl status bitcoind
```

Or check the logs:

```bash
$ sudo journalctl -fu bitcoind
```

## Interacting with the Blockchain

In my [next post](https://dev.to/ruanbekker/interacting-with-your-bitcoin-node-113c) I will demonstrate how to create a wallet, send some test bitcoin to your wallet and how to track transactions on a public block explorer.

## Thank You

Thanks for reading, if you like my content, check out my **[website](https://ruan.dev)** or follow me at **[@ruanbekker](https://twitter.com/ruanbekker)** on Twitter.

The source code of this blog post will be added to this Github Repository:
- https://github.com/ruanbekker/bitcoin-full-node-demo